#This program solves the Navier Stokes equation. It uses the method of
#constructed solutions to test for convergence, which should be 2nd order 

#from __future__ import division
import sys
#import numpy
#print(numpy.__file__)
#import os
#print(os.environ['PYTHONPATH'])
#print sys.path
import numpy as np
import numpy.fft as fft
from numpy import pi 
from pyfft.cl import Plan
import pyopencl as cl
import pyopencl.array as cl_array
from pyopencl.algorithm import RadixSort
from pyopencl.elementwise import ElementwiseKernel
import time
import meshpy.tet as tet
from pyvisfile.vtk import write_structured_grid
from pyvisfile.vtk import (
           UnstructuredGrid, DataArray,
           AppendedDataXMLGenerator,
           VTK_VERTEX, VF_LIST_OF_VECTORS, VF_LIST_OF_COMPONENTS)
from pyvisfile.vtk import (
           UnstructuredGrid, DataArray,
           AppendedDataXMLGenerator,
           VTK_LINE, VTK_TETRA, VTK_TRIANGLE, VF_LIST_OF_VECTORS, VF_LIST_OF_COMPONENTS)
np.set_printoptions(threshold=sys.maxint)
from warnings import filterwarnings
from pyopencl.clrandom import RanluxGenerator
import cPickle as pickle
filterwarnings("ignore", module="pyopencl.cache", lineno=336)
filterwarnings("ignore", module="pyopencl", lineno=163)
TIMING = 0
MONITOR = 0
WGPSIZE_1 = 4
WGPSIZE_2 = 4
WGPSIZE_3 = 4
b_WGPSIZE_1 = 1
b_WGPSIZE_2 = 1
b_WGPSIZE_3 = 1
b_WGPSIZE_4 = 1
PR_INT = 20000 
DISP_INT = 5000
SAVE = 0
#PR_INT = 0
start_size = 6
end_size = 6
ii1 = 7
ii2 = 7
ii3 = 8
#L1 = 1.0
#L2 = 1.0
#L3 = 1.0
L1 = 0.001
L2 = 0.001
L3 = 0.002
INNIE = 0

def retet():
    global b_q, diff_q, N_tet, TW, TV, TW_1_gpu, TW_2_gpu, TW_3_gpu, TW_4_gpu
    global X_1_gpu, X_2_gpu, X_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu
    global F_1_gpu, F_2_gpu, F_3_gpu, U_1_gpu, U_2_gpu, U_3_gpu
    global Rho_gpu, Mu_gpu
    global b_WGPSIZE_2, b_WGPSIZE_3
    #using meshpy
    X_arr = np.hstack((X_1_gpu.get(),X_2_gpu.get(),X_3_gpu.get())).copy()
    points = []
    X_arr = np.vstack((X_arr[0:N_r,:],X_arr[N_r+N_vis:b_q_orig,:])).copy()
    for i in range(0,X_arr.shape[0]):
        points.append((float(X_arr[i,0]),float(X_arr[i,1]),float(X_arr[i,2])))
    info = tet.MeshInfo()
    iii = range(1,N_r+1)
    iii.extend(range(N_r+N_vis+1, b_q_orig+1))
    info.set_points(points, iii)
    info.set_facets(TV_new)
    mesh = tet.build(info)
    temp = len(mesh.points)
    print temp
    TW = np.array(mesh.elements).copy()
    TW_old = TW.copy()
    markers = np.array(mesh.point_markers).copy()
    inds = np.nonzero(markers == 0)[0].copy() 
    #sys.exit()
    if (len(inds) != 0):
        print 'yes1'
        diff_q = len(inds)
        X_arr = np.hstack((X_1_gpu.get(),X_2_gpu.get(),X_3_gpu.get())).copy()
        X_arr = np.vstack((X_arr[0:b_q_orig,:], np.array(mesh.points)[inds,:])).copy()
        X_1_gpu = cl_array.to_device(queue, X_arr[:,0][:,np.newaxis].astype(np.float32))
        X_2_gpu = cl_array.to_device(queue, X_arr[:,1][:,np.newaxis].astype(np.float32))
        X_3_gpu = cl_array.to_device(queue, X_arr[:,2][:,np.newaxis].astype(np.float32))
        X_1_tilde_gpu = cl_array.empty_like(X_1_gpu)
        X_2_tilde_gpu = cl_array.empty_like(X_1_gpu)
        X_3_tilde_gpu = cl_array.empty_like(X_1_gpu)
        U_1_gpu = cl_array.empty_like(X_1_gpu) 
        U_2_gpu = cl_array.empty_like(X_1_gpu) 
        U_3_gpu = cl_array.empty_like(X_1_gpu) 
        b_q = b_q_orig+diff_q 
        if (np.mod(b_q, 8) == 0):
            b_WGPSIZE_2 = 8
        elif (np.mod(b_q, 4) == 0):
            b_WGPSIZE_2 = 4
        elif (np.mod(b_q, 2) == 0):
            b_WGPSIZE_2 = 2
        else:
            b_WGPSIZE_2 = 1
        interp_kernel(queue, (b_q, 1), (b_WGPSIZE_2, 1), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, N1, N2, N3, dx1, dx2, dx3, U_1_gpu.data, U_2_gpu.data, U_3_gpu.data)
        add_gpu(X_1_gpu, U_1_gpu, dt, X_1_tilde_gpu)
        add_gpu(X_2_gpu, U_2_gpu, dt, X_2_tilde_gpu)
        add_gpu(X_3_gpu, U_3_gpu, dt, X_3_tilde_gpu)
        F_1_gpu = cl_array.empty_like(X_1_gpu) 
        F_2_gpu = cl_array.empty_like(X_1_gpu) 
        F_3_gpu = cl_array.empty_like(X_1_gpu) 
        for i in range(0,len(inds)):
            markers[inds[i]] = b_q_orig+i+1
        Rho = rho_l*np.ones((b_q))
        Mu = mu_l*np.ones((b_q))  
        Rho_gpu = cl_array.to_device(queue, Rho.astype(np.float32)) 
        Mu_gpu = cl_array.to_device(queue, Mu.astype(np.float32)) 
    inds = np.nonzero(markers != np.arange(1,temp+1))[0]
    for i in range(len(inds)):
        TW[TW_old == inds[i]] = markers[inds[i]]-1 
    if (len(inds) > diff_q+b_q_orig-N_r-N_vis):
        print 'yes2'
    N_tet = len(mesh.elements) 
    if (np.mod(N_tet, 8) == 0):
        b_WGPSIZE_3 = 8
    elif (np.mod(N_tet, 4) == 0):
        b_WGPSIZE_3 = 4
    elif (np.mod(N_tet, 2) == 0):
        b_WGPSIZE_3 = 2
    else:
        b_WGPSIZE_3 = 1
    print 'new number of tet is', N_tet
    print 'new number of points is', b_q
    TW_1_gpu = cl_array.to_device(queue, TW[:,0].astype(np.uint32))
    TW_2_gpu = cl_array.to_device(queue, TW[:,1].astype(np.uint32))
    TW_3_gpu = cl_array.to_device(queue, TW[:,2].astype(np.uint32))
    TW_4_gpu = cl_array.to_device(queue, TW[:,3].astype(np.uint32))

#lifted from http://stackoverflow.com/questions/1827489/numpy-meshgrid-in-3d
def meshgrid2(*arrs):
    arrs = tuple(reversed(arrs))  #edit
    lens = map(len, arrs)
    dim = len(arrs)

    sz = 1
    for s in lens:
        sz*=s

    ans = []    
    for i, arr in enumerate(arrs):
        slc = [1]*dim
        slc[i] = lens[i]
        arr2 = np.asarray(arr).reshape(slc)
        for j, sz in enumerate(lens):
            if j!=i:
                arr2 = arr2.repeat(sz, axis=j) 
        ans.append(arr2)

    return tuple(ans)

#lifted from http://sites.google.com/site/dlampetest/python/triangulating-a-sphere-recursively 
octahedron_vertices = np.array( [ 
    [ 1.0, 0.0, 0.0], # 0 
    [-1.0, 0.0, 0.0], # 1
    [ 0.0, 1.0, 0.0], # 2 
    [ 0.0,-1.0, 0.0], # 3
    [ 0.0, 0.0, 1.0], # 4 
    [ 0.0, 0.0,-1.0]  # 5                                
    ] )
octahedron_triangles = np.array( [ 
    [ 0, 4, 2 ],
    [ 2, 4, 1 ],
    [ 1, 4, 3 ],
    [ 3, 4, 0 ],
    [ 0, 2, 5 ],
    [ 2, 1, 5 ],
    [ 1, 3, 5 ],
    [ 3, 0, 5 ]] )

def normalize_v3(arr):
    ''' Normalize a numpy array of 3 component vectors shape=(n,3) '''
    lens = np.sqrt( arr[:,0]**2 + arr[:,1]**2 + arr[:,2]**2 )
    arr[:,0] /= lens
    arr[:,1] /= lens
    arr[:,2] /= lens                
    return arr

def normalize_v3_sing(arr):
    ''' Normalize a numpy array of 3 component vectors shape=(n,3) '''
    lens = np.sqrt( arr[0]**2 + arr[1]**2 + arr[2]**2 )
    arr[0] /= lens
    arr[1] /= lens
    arr[2] /= lens                
    return arr

def divide_all( vertices, triangles ):    
    #new_triangles = []
    new_triangle_count = len( triangles ) * 4
    # Subdivide each triangle in the old approximation and normalize
    #  the new points thus generated to lie on the surface of the unit
    #  sphere.
    # Each input triangle with vertices labelled [0,1,2] as shown
    #  below will be turned into four new triangles:
    #
    #            Make new points
    #                 a = (0+2)/2
    #                 b = (0+1)/2
    #                 c = (1+2)/2
    #        1
    #       /\        Normalize a, b, c
    #      /  \
    #    b/____\ c    Construct new triangles
    #    /\    /\       t1 [0,b,a]
    #   /  \  /  \      t2 [b,1,c]
    #  /____\/____\     t3 [a,b,c]
    # 0      a     2    t4 [a,c,2]    
    for i in range(0,triangles.shape[0]):
        v0 = vertices[ triangles[i,0] ]
        v1 = vertices[ triangles[i,1] ]
        v2 = vertices[ triangles[i,2] ]
        a = ( v0+v2 ) * 0.5
        b = ( v0+v1 ) * 0.5
        c = ( v1+v2 ) * 0.5  
        normalize_v3_sing( a )
        normalize_v3_sing( b )
        normalize_v3_sing( c )
    
        #Stack the triangles together.
        if (i == 0):
            new_vertices = np.vstack( (v0,a,b,  b,c,v1,  a,c,b, a,v2,c) )
        else:
            new_vertices = np.vstack( (new_vertices,v0,a,b,  b,c,v1,  a,c,b, a,v2,c) )
        #Now our vertices are duplicated, and thus our triangle structure are unnecesarry.    

   # v0 = vertices[ triangles[:,0] ]
   # v1 = vertices[ triangles[:,1] ]
   # v2 = vertices[ triangles[:,2] ]
   # a = ( v0+v2 ) * 0.5
   # b = ( v0+v1 ) * 0.5
   # c = ( v1+v2 ) * 0.5  
   # normalize_v3( a )
   # normalize_v3( b )
   # normalize_v3( c )
   # 
   # #Stack the triangles together.
   # vertices = np.vstack( (v0,b,a,  b,v1,c,  a,b,c, a,c,v2) )
   # #Now our vertices are duplicated, and thus our triangle structure are unnecesarry.    

    return new_vertices, np.arange( len(new_vertices) ).reshape( (-1,3) )

def make_unique( vertices, triangles ):
    N_tri = triangles.shape[0] 
    N_vert = vertices.shape[0]



    i = 0
    while i < vertices.shape[0] :
        #find indices of repeat vertices
        indices = np.nonzero(np.logical_and(np.logical_and(vertices[:,0] == vertices[i,0],vertices[:,1] == vertices[i,1]),vertices[:,2] == vertices[i,2]))
        indices = indices[0]

        #replace repeats in triangles
        for j in range(0,len(indices)):  
            if (indices[j] != i):
                triangles[triangles == indices[j]] = i 

        for j in range(0,len(indices)):  
            j = len(indices)-1-j
            if (indices[j] != i):
                #delete repeat vertices
                vertices = np.delete(vertices,indices[j],0)
                triangles[triangles > indices[j]] = triangles[triangles > indices[j]] - 1 

        i = i+1

    #delete repeat triangles 
    i = 0
    while i < triangles.shape[0]:
        indices = np.nonzero(np.logical_and(np.logical_and(triangles[:,0] == triangles[i,0],triangles[:,1] == triangles[i,1]),triangles[:,2] == triangles[i,2]))
        indices = indices[0]
    
        for j in range(0,len(indices)):
            if (indices[j] != i):
                triangles = np.delete(triangles,indices[j],0)

        i = i+1
 
    return vertices, triangles

def create_unit_sphere( recursion_level=2 ):
    vertex_array, index_array = octahedron_vertices, octahedron_triangles
    for i in range( recursion_level - 1 ):
        vertex_array, index_array  = divide_all(vertex_array, index_array)

    vertex_array, index_array = make_unique(vertex_array, index_array)    

    i = 0
    #check that triangles have correct orientation
    while i < index_array.shape[0] :
        x1 = vertex_array[index_array[i,0],:]
        x2 = vertex_array[index_array[i,1],:]
        x3 = vertex_array[index_array[i,2],:]

        n = np.cross(x2-x1,x3-x1)
        n = n/np.sqrt(np.dot(n,n))

        if (np.dot(n,x1) < 0):
            print 'negative', np.dot(n,x1)

        i = i+1

    return vertex_array, index_array


def vertex_array_only_unit_sphere( recursion_level=2 ):
    vertex_array, index_array = create_unit_sphere(recursion_level)
    if recursion_level > 1:    
        return vertex_array.reshape( (-1) )
    else:
        return vertex_array[index_array].reshape( (-1) )

def spread_routine2_serial(q, F_1, F_2, F_3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1, f_2, f_3):
    global preind_1, preamt_1 
    global preind_2, preamt_2 
    global preind_3, preamt_3 
    for k in range(0,N_r):
        spread_pre_serial_kernel(q, (1,1), (1, 1), F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, k, N1, N2, N3, dx1, dx2, dx3, dtheta, preind_1.data, preind_2.data, preind_3.data, preamt_1.data, preamt_2.data, preamt_3.data)

def spread_routine2(q, F_1, F_2, F_3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1, f_2, f_3):
    global preind_1, preamt_1 
    global preind_2, preamt_2 
    global preind_3, preamt_3 
    #spread_pre_kernel(q, (N_r,1), (1, 1), F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, preind_1.data, preind_2.data, preind_3.data, preamt_1.data, preamt_2.data, preamt_3.data)
    spread_pre_kernel(q, (N_r+N_spec,1), (1, 1), F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, preind_1.data, preind_2.data, preind_3.data, preamt_1.data, preamt_2.data, preamt_3.data)

    ##start_time = time.time()
    #preind_1, preamt_1, = sort(preind_1, preamt_1, key_bits=32)
    #preind_2, preamt_2, = sort(preind_2, preamt_2, key_bits=32)
    #preind_3, preamt_3, = sort(preind_3, preamt_3, key_bits=32)
    ##print 'time sorting is', time.time()-start_time, 'seconds'
    ##f_1_manual = f_2.get()
    ##start_time = time.time()
    #scan_knl(f_1, preind_1, preamt_1)
    #scan_knl(f_2, preind_2, preamt_2)
    #scan_knl(f_3, preind_3, preamt_3)
    ##print 'time scanning is', time.time()-start_time, 'seconds'

    #preind_1_manual = preind_2.get()
    #preamt_1_manual = preamt_2.get()
    #for i in range(0,64*(N_r+N_spec)): #manual scan
    #   f_1_manual[preind_1_manual[i]] += preamt_1_manual[i] 
    #print np.max(np.abs(f_1_manual-f_2.get()))
    #sys.exit()

def spread_serial_routine(q, firstn1, nextn1, firstn2, nextn2, firstn3, nextn3, F_1, F_2, F_3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1, f_2, f_3):
    shift1 = 0
    shift2 = 0
    for k in range(0,N_r):
        spread_serial_kernel(q, (1,1), (1, 1), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, k, shift1, shift2, f_1.data, f_2.data, f_3.data)

def spread_routine(q, firstn1, nextn1, firstn2, nextn2, firstn3, nextn3, F_1, F_2, F_3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1, f_2, f_3):
    #spread_kernel(q, (1, 1, 1), (1, 1, 1), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, 0, 0, 0, f_1.data, f_2.data, f_3.data)
    #pretest = f_1.get()
    #print pretest[pretest != 0]
    #print firstn1.get()[76,41,38]
    #sys.exit()
    for shift0 in range(0,4):
        for shift1 in range(0,4):
            for shift2 in range(0,4):
                spread_kernel(q, (N1/4, N2/4, N3/4), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, shift0, shift1, shift2, f_1.data, f_2.data, f_3.data)
                #spread_simple_kernel(q, (N1/4, N2/4, N3/4), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, shift0, shift1, shift2, f_1.data, f_2.data, f_3.data)
    #shift0 = 0
    #shift1 = 0
    #shift2 = 0
    #spread_kernel(q, (N1, N2, N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, shift0, shift1, shift2, f_1.data, f_2.data, f_3.data)

def spread_pre_col_routine(q, firstn1, nextn1, firstn2, nextn2, firstn3, nextn3, F_1, F_2, F_3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3, dtheta):
    global precol_1, precol_2, precol_3
    spread_pre_col_kernel(q, (N1, N2), (WGPSIZE_1, WGPSIZE_2), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, precol_1.data, precol_2.data, precol_3.data)

def spread_col_routine(q, firstn1, nextn1, firstn2, nextn2, firstn3, nextn3, F_1, F_2, F_3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1, f_2, f_3):
    for shift0 in range(0,4):
        for shift1 in range(0,4):
            spread_simple_col_kernel(q, (N2/4, N3/4), (16, 16), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, shift0, shift1, f_1.data, f_2.data, f_3.data)
            #spread_col_kernel(q, (N2/4, N3/4), (16, 16), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, F_1.data, F_2.data, F_3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, dtheta, shift0, shift1, f_1.data, f_2.data, f_3.data)

def update_col_routine(q, firstn1, nextn1, firstn2, nextn2, firstn3, nextn3, X_2, X_3, N2, N3, dx2, dx3):
    for shift0 in range(0,4):
        for shift1 in range(0,4):
            updaten_col_kernel(q, (N2/4, N3/4), (16, 16), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, X_2.data, X_3.data, N2, N3, dx2, dx3, shift0, shift1)

def update_spec_routine(q, firstn, nextn, X_1, X_2, X_3, N_pre_spec, N1, N2, N3, dx1, dx2, dx3):
    for shift0 in range(0,4):
        for shift1 in range(0,4):
            for shift2 in range(0,4):
                updaten_spec_kernel(q, (N1/4, N2/4, N3/4), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), firstn.data, nextn.data, X_1.data, X_2.data, X_3.data, N_pre_spec, N1, N2, N3, dx1, dx2, dx3, shift0, shift1, shift2)

def update_routine(q, firstn1, nextn1, firstn2, nextn2, firstn3, nextn3, X_1, X_2, X_3, N1, N2, N3, dx1, dx2, dx3):
    for shift0 in range(0,4):
        for shift1 in range(0,4):
            for shift2 in range(0,4):
                updaten_kernel(q, (N1/4, N2/4, N3/4), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), firstn1.data, nextn1.data, firstn2.data, nextn2.data, firstn3.data, nextn3.data, X_1.data, X_2.data, X_3.data, N1, N2, N3, dx1, dx2, dx3, shift0, shift1, shift2)

def init_col_fn(X_1, X_2, b_q, N1, N2, dx1, dx2):
    global firstn1_col_gpu, nextn1_col_gpu
    global firstn2_col_gpu, nextn2_col_gpu
    global firstn3_col_gpu, nextn3_col_gpu
    firstn1_col = -1*np.ones((N2,N1))
    firstn2_col = -1*np.ones((N2,N1))
    firstn3_col = -1*np.ones((N2,N1))
    nextn1_col = -1*np.ones((b_q,1))
    nextn2_col = -1*np.ones((b_q,1))
    nextn3_col = -1*np.ones((b_q,1))
    start_time = time.time()
    L1 = N1*dx1
    L2 = N2*dx2
    for k in range(0,b_q):
        s_1_stag = (X_1[k]+0.5*L1)/dx1
        s_2_stag = (X_2[k]+0.5*L2)/dx2        
        i_1_stag = (np.remainder(np.floor(s_1_stag),N1)).astype(np.uint32)
        i_2_stag = (np.remainder(np.floor(s_2_stag),N2)).astype(np.uint32)
        s_1_c = (X_1[k]+0.5*L1-dx1/2)/dx1;
        s_2_c = (X_2[k]+0.5*L2-dx2/2)/dx2;        
        i_1_c = (np.remainder(np.floor(s_1_c),N1)).astype(np.uint32);
        i_2_c = (np.remainder(np.floor(s_2_c),N2)).astype(np.uint32);
        if (firstn1_col[i_2_c,i_1_c]==-1):
            firstn1_col[i_2_c,i_1_c]=k 
        else:
            nextn1_col[k]=firstn1_col[i_2_c,i_1_c]
            firstn1_col[i_2_c,i_1_c]=k
        if (firstn2_col[i_2_c,i_1_stag]==-1):
            firstn2_col[i_2_c,i_1_stag]=k 
        else:
            nextn2_col[k]=firstn2_col[i_2_c,i_1_stag]
            firstn2_col[i_2_c,i_1_stag]=k
        if (firstn3_col[i_2_stag,i_1_c]==-1):
            firstn3_col[i_2_stag,i_1_c]=k 
        else:
            nextn3_col[k]=firstn3_col[i_2_stag,i_1_c]
            firstn3_col[i_2_stag,i_1_c]=k
    print 'time spent binning points is', time.time()-start_time, 'seconds'
    firstn1_col_gpu = cl_array.to_device(queue, firstn1_col.astype(np.int32))
    nextn1_col_gpu = cl_array.to_device(queue, nextn1_col.astype(np.int32))
    firstn2_col_gpu = cl_array.to_device(queue, firstn2_col.astype(np.int32))
    nextn2_col_gpu = cl_array.to_device(queue, nextn2_col.astype(np.int32))
    firstn3_col_gpu = cl_array.to_device(queue, firstn3_col.astype(np.int32))
    nextn3_col_gpu = cl_array.to_device(queue, nextn3_col.astype(np.int32))

def init_spec_fn(X_1, X_2, X_3, b_q, N_pre, N1, N2, N3, dx1, dx2, dx3):
    global firstn_spec_gpu, nextn_spec_gpu
    firstn_spec = -1*np.ones((N3,N2,N1)).astype(np.uint32)
    nextn_spec = -1*np.ones((b_q,1)).astype(np.uint32)
    L1 = N1*dx1
    L2 = N2*dx2
    L3 = N3*dx3
    #el_spec = np.zeros((N3,N2,N1))
    start_time = time.time()
    for k in range(0,b_q):
        s_1_stag = (X_1[k+N_pre]+0.5*L1)/dx1
        s_2_stag = (X_2[k+N_pre]+0.5*L2)/dx2        
        s_3_stag = (X_3[k+N_pre]+0.5*L3)/dx3        
        i_1_stag = (np.remainder(np.floor(s_1_stag),N1)).astype(np.uint32)
        i_2_stag = (np.remainder(np.floor(s_2_stag),N2)).astype(np.uint32)
        i_3_stag = (np.remainder(np.floor(s_3_stag),N3)).astype(np.uint32)
        s_1_c = (X_1[k+N_pre]+0.5*L1-dx1/2)/dx1;
        s_2_c = (X_2[k+N_pre]+0.5*L2-dx2/2)/dx2;        
        s_3_c = (X_3[k+N_pre]+0.5*L3-dx3/2)/dx3;        
        i_1_c = (np.remainder(np.floor(s_1_c),N1)).astype(np.uint32);
        i_2_c = (np.remainder(np.floor(s_2_c),N2)).astype(np.uint32);
        i_3_c = (np.remainder(np.floor(s_3_c),N3)).astype(np.uint32);
        if (firstn_spec[i_3_stag,i_2_stag,i_1_stag]==-1):
            firstn_spec[i_3_stag,i_2_stag,i_1_stag]=k 
        else:
            nextn_spec[k]=firstn_spec[i_3_stag,i_2_stag,i_1_stag]
            firstn_spec[i_3_stag,i_2_stag,i_1_stag]=k
        #i_1_m = np.mod(i_1_stag-1,N1)
        #i_1_p = np.mod(i_1_stag+1,N1)
        #i_2_m = np.mod(i_2_stag-1,N2)
        #i_2_p = np.mod(i_2_stag+1,N2)
        #i_3_m = np.mod(i_3_stag-1,N3)
        #i_3_p = np.mod(i_3_stag+1,N3)
        #i_1 = np.array([i_1_m,i_1_stag,i_1_p])
        #i_2 = np.array([i_2_m,i_2_stag,i_2_p])
        #i_3 = np.array([i_3_m,i_3_stag,i_3_p])
        #for ii in range(0,3):
        #    for jj in range(0,3):
        #        for kk in range(0,3):
        #            el_spec[i_3[kk],i_2[jj],i_1[ii]] += 1
    print 'time spent binning points is', time.time()-start_time, 'seconds'
    #print 'max el is', np.max(el_spec) 
    #print 'avg el is', np.mean(el_spec) 
    #el_pairs = np.zeros((b_q,1))
    #for ii in range(0,N1):
    #    i_1_m = np.mod(ii-1,N1)
    #    i_1_p = np.mod(ii+1,N1)
    #    for jj in range(0,N2):
    #        i_2_m = np.mod(jj-1,N2)
    #        i_2_p = np.mod(jj+1,N2)
    #        for kk in range(0,N3):
    #            i_3_m = np.mod(kk-1,N3)
    #            i_3_p = np.mod(kk+1,N3)
    #            i_1 = np.array([i_1_m,i_1_stag,i_1_p])
    #            i_2 = np.array([i_2_m,i_2_stag,i_2_p])
    #            i_3 = np.array([i_3_m,i_3_stag,i_3_p])
    #            k = firstn_spec[kk,jj,ii]
    #            while (k != -1):
    #                for ii2 in range(0,3):
    #                    for jj2 in range(0,3):
    #                        for kk2 in range(0,3):
    #                            k2 = firstn_spec[i_3[kk2],i_2[jj2],i_1[ii2]] 
    #                            while (k2 != -1):
    #                                length = np.sqrt((X_1[k+N_pre]-X_1[k2+N_pre])**2+(X_2[k+N_pre]-X_2[k2+N_pre])**2+(X_3[k+N_pre]-X_3[k2+N_pre])**2)
    #                                if (length < L_cont):
    #                                    el_pairs[k] += 1
    #                                k2 = nextn_spec[k2]
    #                k = nextn_spec[k]
    #print 'max el pairs is', np.max(el_pairs) 
    #print 'avg el pairs is', np.mean(el_pairs) 
    firstn_spec_gpu = cl_array.to_device(queue, firstn_spec.astype(np.int32))
    nextn_spec_gpu = cl_array.to_device(queue, nextn_spec.astype(np.int32))

def init_fn(X_1, X_2, X_3, b_q, N1, N2, N3, dx1, dx2, dx3):
    global firstn1_gpu, nextn1_gpu
    global firstn2_gpu, nextn2_gpu
    global firstn3_gpu, nextn3_gpu
    firstn1 = -1*np.ones((N3,N2,N1))
    #firstn1 = -1*np.ones((N1,N2,N3))
    nextn1 = -1*np.ones((b_q,1))
    firstn2 = -1*np.ones((N3,N2,N1))
    #firstn2 = -1*np.ones((N1,N2,N3))
    nextn2 = -1*np.ones((b_q,1))
    firstn3 = -1*np.ones((N3,N2,N1))
    #firstn3 = -1*np.ones((N1,N2,N3))
    nextn3 = -1*np.ones((b_q,1))
    start_time = time.time()
    L1 = N1*dx1
    L2 = N2*dx2
    L3 = N3*dx3
    #numn1 = np.zeros((N3,N2,N1))
    for k in range(0,b_q):
        s_1_stag = (X_1[k]+0.5*L1)/dx1
        s_2_stag = (X_2[k]+0.5*L2)/dx2        
        s_3_stag = (X_3[k]+0.5*L3)/dx3        
        i_1_stag = (np.remainder(np.floor(s_1_stag),N1)).astype(np.uint32)
        i_2_stag = (np.remainder(np.floor(s_2_stag),N2)).astype(np.uint32)
        i_3_stag = (np.remainder(np.floor(s_3_stag),N3)).astype(np.uint32)
        s_1_c = (X_1[k]+0.5*L1-dx1/2)/dx1;
        s_2_c = (X_2[k]+0.5*L2-dx2/2)/dx2;        
        s_3_c = (X_3[k]+0.5*L3-dx3/2)/dx3;        
        i_1_c = (np.remainder(np.floor(s_1_c),N1)).astype(np.uint32);
        i_2_c = (np.remainder(np.floor(s_2_c),N2)).astype(np.uint32);
        i_3_c = (np.remainder(np.floor(s_3_c),N3)).astype(np.uint32);
        if (firstn1[i_3_c,i_2_c,i_1_stag]==-1):
            firstn1[i_3_c,i_2_c,i_1_stag]=k 
        else:
            nextn1[k]=firstn1[i_3_c,i_2_c,i_1_stag]
            firstn1[i_3_c,i_2_c,i_1_stag]=k
        #numn1[i_3_c,i_2_c,i_1_stag] += 1
        if (firstn2[i_3_c,i_2_stag,i_1_c]==-1):
            firstn2[i_3_c,i_2_stag,i_1_c]=k 
        else:
            nextn2[k]=firstn2[i_3_c,i_2_stag,i_1_c]
            firstn2[i_3_c,i_2_stag,i_1_c]=k
        if (firstn3[i_3_stag,i_2_c,i_1_c]==-1):
            firstn3[i_3_stag,i_2_c,i_1_c]=k 
        else:
            nextn3[k]=firstn3[i_3_stag,i_2_c,i_1_c]
            firstn3[i_3_stag,i_2_c,i_1_c]=k
    #print np.max(numn1)
    #print np.mean(numn1[numn1 != 0])
    #sys.exit()
    print 'time spent binning points is', time.time()-start_time, 'seconds'
    firstn1_gpu = cl_array.to_device(queue, firstn1.astype(np.int32))
    nextn1_gpu = cl_array.to_device(queue, nextn1.astype(np.int32))
    firstn2_gpu = cl_array.to_device(queue, firstn2.astype(np.int32))
    nextn2_gpu = cl_array.to_device(queue, nextn2.astype(np.int32))
    firstn3_gpu = cl_array.to_device(queue, firstn3.astype(np.int32))
    nextn3_gpu = cl_array.to_device(queue, nextn3.astype(np.int32))

def calc_transf(N1, N2, N3, dx1, dx2, dx3):
    k1 = np.arange(0, N1/2+1)
    k1 = np.hstack([k1, np.arange(-N1/2+1, 0)])
    k1 = np.tile(k1, (N3, N2, 1))
    #k1 = np.tile(k1.reshape(N1,1,1), (1,N2,N3))
    k2 = np.arange(0, N2/2+1)
    k2 = np.hstack([k2, np.arange(-N2/2+1, 0)])
    k2 = np.tile(k2.reshape(N2,1), (N3, 1, N1))
    #k2 = np.tile(k2.reshape(1,N2,1), (N1, 1, N3))
    k3 = np.arange(0, N3/2+1)
    k3 = np.hstack([k3, np.arange(-N3/2+1, 0)])
    k3 = np.tile(k3.reshape(N3,1,1), (1, N2, N1))
    #k3 = np.tile(k3.reshape(1,1,N3), (N1, N2, 1))
    L_tf = (-4./dx1**2)*np.sin(pi*k1/N1)**2+(-4./dx2**2)*np.sin(pi*k2/N2)**2+(-4./dx3**2)*np.sin(pi*k3/N3)**2 
    L_tf[0,0,0] = 1. #avoid dividing by zero
    return L_tf

def solve(t_step):
    global rho_av
    imag_gpu(u_1_gpu, u_1_tf_gpu)
    imag_gpu(u_2_gpu, u_2_tf_gpu)
    imag_gpu(u_3_gpu, u_3_tf_gpu)

    plan.execute(u_1_tf_gpu.data)
    plan.execute(u_2_tf_gpu.data)
    plan.execute(u_3_tf_gpu.data)

    interp_kernel(queue, (b_q, 1), (b_WGPSIZE_2, 1), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, N1, N2, N3, dx1, dx2, dx3, U_1_gpu.data, U_2_gpu.data, U_3_gpu.data)

    if INNIE:
        zero_gpu(en_gpu)
        calc_total_area_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, k_area, N_tri, en_gpu.data) 
        ar = en_gpu.get()[0]
        zero_gpu(en_gpu)
        calc_energy_volume_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, N_tri, en_gpu.data) 
        vol = np.abs(en_gpu.get()[0])
        s_0 = 0.0
        if ((vol-vol_t)/vol_t > 0.001):
            s_0 = s_00 
        zero_gpu(F_1_gpu)
        zero_gpu(F_2_gpu)
        zero_gpu(F_3_gpu)
        calc_nrml_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, CT_gpu.data, CT_max, k_area, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data, 0)
        calc_nrml_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_spec_1_gpu.data, TV_spec_2_gpu.data, TV_spec_3_gpu.data, A_0_gpu.data, CT_spec_gpu.data, CT_max, k_area, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data, N_pre_spec)
        add_gpu(U_1_gpu, F_1_gpu, -s_0, U_1_gpu)
        add_gpu(U_2_gpu, F_2_gpu, -s_0, U_2_gpu)
        add_gpu(U_3_gpu, F_3_gpu, -s_0, U_3_gpu)

    #if (t_step < 5000):
    #    proj_sphere_kernel(queue, (b_q, 1), (b_WGPSIZE_2, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, N_pre_spec, U_1_gpu.data, U_2_gpu.data, U_3_gpu.data)

    add_gpu(X_1_gpu, U_1_gpu, dt, X_1_tilde_gpu)
    add_gpu(X_2_gpu, U_2_gpu, dt, X_2_tilde_gpu)
    add_gpu(X_3_gpu, U_3_gpu, dt, X_3_tilde_gpu)

    #rangen1.fill_uniform(break_spec_gpu, queue=queue)
    ##break some bonds
    #symm_break_spec_kernel(queue, (N_spec, CX_max), (b_WGPSIZE_4, 1), break_spec_gpu.data, CX_gpu.data, CX_max, 0) 
    ##symm_break_spec_kernel(queue, (40000, CX_max), (400, 1), break_spec_gpu.data, CX_gpu.data, CX_max, 0) 
    ##symm_break_spec_kernel(queue, (N_spec-40000, CX_max), (1, 1), break_spec_gpu.data, CX_gpu.data, CX_max, 40000) 
    #break_spec_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), break_spec_gpu.data, kbrk, dt, CX_gpu.data, CX_max, 0) 
    ##break_spec_kernel(queue, (40000, 1), (400, 1), break_spec_gpu.data, kbrk, dt, CX_gpu.data, CX_max, 0) 
    ##break_spec_kernel(queue, (N_spec-40000, 1), (1, 1), break_spec_gpu.data, kbrk, dt, CX_gpu.data, CX_max, 40000) 
    ##make some bonds
    #update_spec_routine(queue, firstn_spec_gpu, nextn_spec_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec)
    ##set_int_gpu(-1, count_el_gpu)
    #count_make_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 0)
    ##count_make_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 0)
    ##count_make_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 40000)
    #simple_scan_knl(count_el_gpu, queue=queue)
    ##set_int_gpu(-1, CX_el_gpu)
    #fill_make_new_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_el_gpu.data, CX_max, 0)
    ##fill_make_new_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_el_gpu.data, CX_max, 0)
    ##fill_make_new_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_el_gpu.data, CX_max, 40000)
    ##fill_make_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, CX_el_gpu.data, CX_max, CX_el_max, 0)
    ##fill_make_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, CX_el_gpu.data, CX_max, CX_el_max, 40000)
    #rangen2.fill_uniform(make_spec_gpu, queue=queue)
    ##copy_gpu(CX_gpu, CX_test_gpu)
    ##zero_gpu(en_gpu)
    ##symm_test_kernel(queue, (N_spec, CX_el_max), (b_WGPSIZE_4, 1), en_gpu.data, CX_el_gpu.data, CX_el_max, 0) 
    ##print en_gpu.get()[0]
    #symm_make_spec_new_kernel(queue, (N_spec, CX_el_max), (b_WGPSIZE_4, 1), make_spec_gpu.data, CX_el_gpu.data, count_el_gpu.data, 0) 
    ##symm_make_spec_new_kernel(queue, (40000, 1), (400, 1), make_spec_gpu.data, CX_el_gpu.data, count_el_gpu.data, 0) 
    ##symm_make_spec_new_kernel(queue, (N_spec-40000, 1), (1, 1), make_spec_gpu.data, CX_el_gpu.data, count_el_gpu.data, 40000) 
    ##symm_make_spec_kernel(queue, (40000, CX_el_max), (400, 1), make_spec_gpu.data, CX_el_gpu.data, CX_el_max, 0) 
    ##symm_make_spec_kernel(queue, (N_spec-40000, CX_el_max), (1, 1), make_spec_gpu.data, CX_el_gpu.data, CX_el_max, 40000) 
    #make_spec_new_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_el_gpu.data, make_spec_gpu.data, myfun_gpu.data, N_pre_spec, tablesize, L_cont, kbrk, dt, CX_gpu.data, count_el_gpu.data, CX_max, 0) 
    ##make_spec_new_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_el_gpu.data, make_spec_gpu.data, myfun_gpu.data, N_pre_spec, tablesize, L_cont, kbrk, dt, CX_gpu.data, count_el_gpu.data, CX_max, 0) 
    ##make_spec_new_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_el_gpu.data, make_spec_gpu.data, myfun_gpu.data, N_pre_spec, tablesize, L_cont, kbrk, dt, CX_gpu.data, count_el_gpu.data, CX_max, 40000) 
    ##make_spec_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_el_gpu.data, make_spec_gpu.data, myfun_gpu.data, N_pre_spec, tablesize, L_cont, kbrk, dt, CX_gpu.data, CX_el_max, CX_max, 0) 
    ##make_spec_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_el_gpu.data, make_spec_gpu.data, myfun_gpu.data, N_pre_spec, tablesize, L_cont, kbrk, dt, CX_gpu.data, CX_el_max, CX_max, 40000) 
    ###zero_gpu(en_gpu)
    ###symm_test_kernel(queue, (N_spec, CX_max), (b_WGPSIZE_4, 1), en_gpu.data, CX_gpu.data, CX_max, 0) 
    ###print en_gpu.get()[0]

    if MONITOR:
        zero_gpu(monitor_gpu)
        monitor_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), CX_gpu.data, CX_max, monitor_gpu.data)
        if (np.max(monitor_gpu.get()) > CX_max-2):
            print 'monitor 1 alert'
        #monitor_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), CX_el_gpu.data, CX_el_max, monitor_gpu.data)
        count_make_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 0)
        #count_make_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 0)
        #count_make_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 40000)
        if (np.mean(count_el_gpu.get()) > CX_el_max-2):
            print 'monitor 2 alert'

    ##test
    #CX_el = CX_el_gpu.get()
#
#    CX_test = -1*np.ones((N_spec, CX_el_max))
#    for k in range(0,N_spec):
#        dists = (X_1-X_1[k])**2+(X_2-X_2[k])**2+(X_3-X_3[k])**2 
#        inds = np.nonzero(dists < L_cont*L_cont)[0].copy()
#        szI = inds.shape[0]
#        #print szI
#        #print inds.shape
#        #temp = CX_test[k,0:szI]
#        #print temp.shape
#        CX_test[k,0:szI] = inds
#        if k % 1000 == 0:
#            print k
#    CX_el = np.sort(CX_el) 
#    CX_test = np.sort(CX_test) 
#    print np.max(CX_el-CX_test)
#    sys.exit()

    ##change mu_hat for predictor
    #mu_hat = 0.5*(mu_max+mu_min)

    #complex_mult_gpu(L_tf_gpu, u_1_tf_gpu,u_1_tf_gpu) 
    #plan.execute(u_1_tf_gpu.data, inverse=True)
    #real_gpu(u_1_tf_gpu, u_1_gpu)
    ##Lu1_tf = L_tf*u_1_tf_gpu.get()
    #Lu1_ex = -8*pi**2/L1**2*np.cos(2*pi/L1*xx_1_stag)-32*pi**2/L2**2*np.sin(4*pi/L2*xx_2_c) 
    #print u_1_gpu.get().shape
    #print np.abs(u_1_gpu.get()).max()
    #print Lu1_ex.shape
    #print np.abs(Lu1_ex).max()
    #print u_1_gpu.get()
    #print Lu1_ex
    #diff = np.abs(u_1_gpu.get()-Lu1_ex).max()
    #print diff
    #sys.exit()
    
    if (CHECK_TET_FLAG == 1):
        check_tet_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, en_gpu.data) 
        zero_gpu(en_gpu)
    if (en_gpu.get()[0] == 1.0):
        print 'retet 0'
        retet()
        zero_gpu(en_gpu)
        check_tet_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, en_gpu.data) 
        if (en_gpu.get()[0] == 1.0):
            print 'wrong assumption'
            #sys.exit()
        zero_gpu(en_gpu)
        check_tet_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, en_gpu.data) 
        if (en_gpu.get()[0] == 1.0):
            print 'trouble'
            #sys.exit()

    if (CHECK_TET_FLAG == 1):
        check_tet_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, en_gpu.data) 
        zero_gpu(en_gpu)
    if (en_gpu.get()[0] == 1.0):
        print 'retet 1'
        retet()
        zero_gpu(en_gpu)
        check_tet_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, en_gpu.data) 
        if (en_gpu.get()[0] == 1.0):
            print 'wrong assumption'
            #sys.exit()
        zero_gpu(en_gpu)
        check_tet_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, en_gpu.data) 
        if (en_gpu.get()[0] == 1.0):
            print 'trouble'
            #sys.exit()

    #calc_lagF_gpu(X_1_gpu, X_2_gpu, X_3_gpu, rr_lag_gpu, ip_s_lag_gpu, im_s_lag_gpu, ds, F_1_gpu, F_2_gpu, F_3_gpu)
    zero_gpu(F_1_gpu)
    zero_gpu(F_2_gpu)
    zero_gpu(F_3_gpu)

    calc_lagF_spec_new_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_gpu.data, CX_max, N_pre_spec, k_spec, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    if (t_step < 200000):
        proj_tri_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, tri_ind_gpu.data, N_pre_spec, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_area_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, CT_gpu.data, CT_max, k_area, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #scale_gpu(F_1_gpu, da, F_1_gpu)
    #scale_gpu(F_2_gpu, da, F_2_gpu)
    #scale_gpu(F_3_gpu, da, F_3_gpu)
    calc_lagF_curv_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, CT_gpu.data, CT_max, k_curv, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    calc_lagF_hook_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, X_ref_1_gpu.data, X_ref_2_gpu.data, X_ref_3_gpu.data, CT_gpu.data, CT_max, k_bulk, k_shear, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_curv_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, CT_gpu.data, CT_max, k_curv, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_hook_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, X_ref_1_gpu.data, X_ref_2_gpu.data, X_ref_3_gpu.data, CT_gpu.data, CT_max, k_bulk, k_shear, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_wlc_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, fe_1_gpu.data, fe_2_gpu.data, CE_gpu.data, CE_max, N_pre_spec, k_wlc, L_cont, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_wlc_new_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, CX_gpu.data, CX_max, N_pre_spec, k_wlc, L_cont, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #zero_gpu(U_1_gpu)
    #zero_gpu(U_2_gpu)
    #zero_gpu(U_3_gpu)
    #zero_gpu(F_1_gpu)
    #zero_gpu(F_2_gpu)
    #zero_gpu(F_3_gpu)
    #calc_lagF_spec_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, fe_1_gpu.data, fe_2_gpu.data, CE_gpu.data, CE_max, N_pre_spec, k_spec, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    
    #print np.max(np.abs(F_1_gpu.get()))
    #print np.max(np.abs(U_1_gpu.get()))
    #print np.max(np.abs(F_1_gpu.get()-U_1_gpu.get()))
    #print np.max(np.abs(F_2_gpu.get()))
    #print np.max(np.abs(F_2_gpu.get()-U_2_gpu.get()))
    #print np.max(np.abs(F_3_gpu.get()))
    #print np.max(np.abs(F_3_gpu.get()-U_3_gpu.get()))
    #sys.exit()

    #zero_gpu(precol_1)
    #zero_gpu(precol_2)
    #zero_gpu(precol_3)
    zero_gpu(f_1_gpu)
    zero_gpu(f_2_gpu)
    zero_gpu(f_3_gpu)
    #zero_gpu(u_1_tilde_gpu)
    #zero_gpu(u_2_tilde_gpu)
    #zero_gpu(u_3_tilde_gpu)
    #zero_gpu(mu_1_gpu)
    #zero_gpu(mu_2_gpu)
    #zero_gpu(mu_3_gpu)
    #zero_gpu(rho_1_gpu)
    #zero_gpu(rho_2_gpu)
    #zero_gpu(rho_3_gpu)

    #zero_gpu(f_1_flat_gpu)
    #zero_gpu(f_2_flat_gpu)
    #zero_gpu(f_3_flat_gpu)
    #f_1_manual = f_3_flat_gpu.get()
    ##spread_routine2_serial(queue, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1_flat_gpu, f_2_flat_gpu, f_3_flat_gpu)
    #spread_routine2(queue, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1_flat_gpu, f_2_flat_gpu, f_3_flat_gpu)
    update_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3)
    #spread_serial_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1_gpu, f_2_gpu, f_3_gpu)
    spread_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1_gpu, f_2_gpu, f_3_gpu)
    #update_col_routine(queue, firstn1_col_gpu, nextn1_col_gpu, firstn2_col_gpu, nextn2_col_gpu, firstn3_col_gpu, nextn3_col_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N2, N3, dx2, dx3)
    #spread_pre_col_routine(queue, firstn1_col_gpu, nextn1_col_gpu, firstn2_col_gpu, nextn2_col_gpu, firstn3_col_gpu, nextn3_col_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta)
    #spread_col_routine(queue, firstn1_col_gpu, nextn1_col_gpu, firstn2_col_gpu, nextn2_col_gpu, firstn3_col_gpu, nextn3_col_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, u_1_tilde_gpu, u_2_tilde_gpu, u_3_tilde_gpu)
    #sum_col_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), precol_1.data, precol_2.data, precol_3.data, N1, N2, N3, u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data)
    ##print np.max(np.abs(f_1_gpu.get().flatten()-f_1_flat_gpu.get()[0:N1*N2*N3]))
    ##print np.max(np.abs(f_2_gpu.get().flatten()-f_2_flat_gpu.get()[0:N1*N2*N3]))
    ##print np.max(np.abs(f_3_gpu.get().flatten()-f_3_flat_gpu.get()[0:N1*N2*N3]))
    ##print np.mean(np.abs(f_1_gpu.get().flatten()-f_1_flat_gpu.get()[0:N1*N2*N3]))
    ##print np.mean(np.abs(f_2_gpu.get().flatten()-f_2_flat_gpu.get()[0:N1*N2*N3]))
    ##print np.mean(np.abs(f_3_gpu.get().flatten()-f_3_flat_gpu.get()[0:N1*N2*N3]))
    #preind_1_manual = preind_3.get()
    #preamt_1_manual = preamt_3.get()
    #for i in range(0,64*(N_r)): #manual scan
    ##for i in range(0,64*(N_r+N_spec)): #manual scan
    #   f_1_manual[preind_1_manual[i]] = f_1_manual[preind_1_manual[i]]+preamt_1_manual[i] 
    ##print np.max(np.abs(f_1_gpu.get()-u_1_gpu.get()))
    #print np.max(np.abs(f_1_gpu.get()))
    #print np.max(np.abs(u_1_tilde_gpu.get()))
    #print np.max(np.abs(f_1_gpu.get()-u_1_tilde_gpu.get()))
    #print np.max(np.abs(f_2_gpu.get()))
    #print np.max(np.abs(f_2_gpu.get()-u_2_tilde_gpu.get()))
    #print np.max(np.abs(f_3_gpu.get()))
    #print np.max(np.abs(f_3_gpu.get()-u_3_tilde_gpu.get()))
    #print np.max(np.abs(f_3_gpu.get().flatten()-f_1_manual[0:N1*N2*N3]))
    ##test power conservation
    ##print np.sum(u_3_gpu.get()*f_3_gpu.get())*dx1*dx2*dx3
    ##print np.sum(u_3_gpu.get().flatten()*f_1_manual[0:N1*N2*N3])*dx1*dx2*dx3
    ##print np.sum(U_3_gpu.get()*F_3_gpu.get())*dtheta
    #sys.exit()
    ##copy_gpu(f_1_flat_gpu, f_1_gpu)
    ##copy_gpu(f_2_flat_gpu, f_2_gpu)
    ##copy_gpu(f_3_flat_gpu, f_3_gpu)

    #spread_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_gpu, X_2_gpu, X_3_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, u_1_tilde_gpu, u_2_tilde_gpu, u_3_tilde_gpu)
    #print np.max(u_1_tilde_gpu.get())

    #print u_1_tilde_gpu.get()
    #sys.exit()
    
    add_gpu(f_3_gpu, body_gpu, body_f, f_3_gpu)
    #calc_f_gpu((t_step-1)*dt, mu_0, rho_0, xx_1_stag_gpu, xx_2_stag_gpu, xx_3_stag_gpu, xx_1_c_gpu, xx_2_c_gpu, xx_3_c_gpu, u_1_tilde_gpu, u_2_tilde_gpu, u_3_tilde_gpu)

    #calc_coefs_kernel(queue, (N_tet, 1), (b_WGPSIZE_3,1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, Rho_gpu.data, Mu_gpu.data, dx1, dx2, dx3, N1, N2, N3, rho_1_gpu.data, rho_2_gpu.data, rho_3_gpu.data, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data) 
    ##print 'av force is', np.mean(u_3_tilde_gpu.get())
    #zero_gpu(en_sum_gpu)
    #calc_rho_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, Rho_gpu.data, en_sum_gpu.data)

    #rho_av = (en_sum_gpu.get().sum()+dx1*dx2*dx3*N1*N2*N3)/(dx1*dx2*dx3*N1*N2*N3)
    #rho_av = (rho_0*N1*N2*N3+rho_3_gpu.get().sum())/(N1*N2*N3) 

    #add_gpu(u_3_tilde_gpu, rho_0-rho_av+rho_3_gpu, -grav, u_3_tilde_gpu)

    #add_scalar_gpu(mu_1_gpu, -mu_bar, mu_1_gpu)
    #add_scalar_gpu(mu_2_gpu, -mu_bar, mu_2_gpu)
    #add_scalar_gpu(mu_3_gpu, -mu_bar, mu_3_gpu)
    #add_scalar_gpu(rho_1_gpu, rho_0-rho_hat, rho_1_gpu)
    #add_scalar_gpu(rho_2_gpu, rho_0-rho_hat, rho_2_gpu)
    #add_scalar_gpu(rho_3_gpu, rho_0-rho_hat, rho_3_gpu)

    #print 'av force is', np.mean(u_3_tilde_gpu.get())

    #check power identity
    #print 'power is', (U_1_gpu.get()*F_1_gpu.get()+U_2_gpu.get()*F_2_gpu.get()+U_3_gpu.get()*F_3_gpu.get()).sum()*dtheta-(u_1_tilde_gpu.get()*u_1_gpu.get()+u_2_tilde_gpu.get()*u_2_gpu.get()+u_3_tilde_gpu.get()*u_3_gpu.get()).sum()*dx*dx*dx
    #print 'power is', (U_1_gpu.get()*F_1_gpu.get()+U_2_gpu.get()*F_2_gpu.get()).sum()*dtheta-(u_1_tilde_gpu.get()*u_1_gpu.get()+u_2_tilde_gpu.get()*u_2_gpu.get()).sum()*dx*dx*dx
    #check momentum conservation
    #print 'mom1 is', (u_1_gpu.get()*(rho_1_gpu.get()+rho_0)).sum()*dx*dx*dx
    #print 'mom2 is', (u_2_gpu.get()*(rho_2_gpu.get()+rho_0)).sum()*dx*dx*dx
    #print 'mom3 is', (u_3_gpu.get()*(rho_3_gpu.get()+rho_0)).sum()*dx*dx*dx
    #print (U_1_gpu.get()*F_1_gpu.get()+U_2_gpu.get()*F_2_gpu.get()).sum()*dtheta

    #add_gpu(f_1_gpu, u_1_tilde_gpu, 1, f_1_gpu) 
    #add_gpu(f_2_gpu, u_2_tilde_gpu, 1, f_2_gpu) 
    #add_gpu(f_3_gpu, u_3_tilde_gpu, 1, f_3_gpu) 

    #vc_laplace_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data) 

    #add_gpu(f_1_gpu, u_1_tilde_gpu, 1.0, f_1_gpu) 
    #add_gpu(f_2_gpu, u_2_tilde_gpu, 1.0, f_2_gpu) 
    #add_gpu(f_3_gpu, u_3_tilde_gpu, 1.0, f_3_gpu) 

    #ss_conv_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data)
    ss_conv_fast_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data)
    #zero_gpu(u_1_tilde_gpu) #turn off convection
    #zero_gpu(u_2_tilde_gpu)
    #zero_gpu(u_3_tilde_gpu)

    add_gpu(f_1_gpu, u_1_tilde_gpu, -rho_hat, f_1_gpu)
    add_gpu(f_2_gpu, u_2_tilde_gpu, -rho_hat, f_2_gpu)
    add_gpu(f_3_gpu, u_3_tilde_gpu, -rho_hat, f_3_gpu)

    #dal_term_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, u_1_o_gpu.data, u_2_o_gpu.data, u_3_o_gpu.data, u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data, rho_1_gpu.data, rho_2_gpu.data, rho_3_gpu.data, dt, N1, N2, N3, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data)

    #copy_gpu(u_1_gpu, u_1_o_gpu)
    #copy_gpu(u_2_gpu, u_2_o_gpu)
    #copy_gpu(u_3_gpu, u_3_o_gpu)

    copy_gpu(f_1_gpu, u_1_tilde_gpu)
    copy_gpu(f_2_gpu, u_2_tilde_gpu)
    copy_gpu(f_3_gpu, u_3_tilde_gpu)

    #add_gpu(f_1_gpu, mu_1_gpu, -1.0, f_1_gpu)
    #add_gpu(f_2_gpu, mu_2_gpu, -1.0, f_2_gpu)
    #add_gpu(f_3_gpu, mu_3_gpu, -1.0, f_3_gpu)

    ##FE STEP
    #add_gpu(u_1_gpu, f_1_gpu, dt, u_1_gpu)
    #add_gpu(u_2_gpu, f_2_gpu, dt, u_2_gpu)
    #add_gpu(u_3_gpu, f_3_gpu, dt, u_3_gpu)
    #return
    #print "test"
    ##########################################################solve for u_tilde
    div_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), f_1_gpu.data, f_2_gpu.data, f_3_gpu.data, dx1, dx2, dx3, N1, N2, N3, p_gpu.data)
    imag_gpu(p_gpu, p_tf_gpu)
    plan.execute(p_tf_gpu.data)

    L_adj_2_kernel(queue, (1,1), (1,1), L_tf_gpu.data)
    calc_p_gpu(p_tf_gpu, L_tf_gpu, p_tf_gpu)
    p_filt_kernel(queue, (1,1), (1,1), p_tf_gpu.data)
    plan.execute(p_tf_gpu.data, inverse=True)
    real_gpu(p_tf_gpu, p_gpu)

    #print np.max(p_gpu.get())
    #sys.exit()

    grad_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), p_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data)

    add_gpu(f_1_gpu, u_1_gpu, -1, f_1_gpu)
    add_gpu(f_2_gpu, u_2_gpu, -1, f_2_gpu)
    add_gpu(f_3_gpu, u_3_gpu, -1, f_3_gpu)

    imag_gpu(f_1_gpu, f_1_tf_gpu)
    imag_gpu(f_2_gpu, f_2_tf_gpu)
    imag_gpu(f_3_gpu, f_3_tf_gpu)

    plan.execute(f_1_tf_gpu.data)
    plan.execute(f_2_tf_gpu.data)
    plan.execute(f_3_tf_gpu.data)

    L_adj_1_kernel(queue, (1,1), (1,1), L_tf_gpu.data)
    solve_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_tf_gpu.data, u_2_tf_gpu.data, u_3_tf_gpu.data, L_tf_gpu.data, f_1_tf_gpu.data, f_2_tf_gpu.data, f_3_tf_gpu.data, dt, rho_hat, mu_0-mu_hat, mu_hat, N1, N2, N3, f_1_tf_gpu.data, f_2_tf_gpu.data, f_3_tf_gpu.data)

    #nyq_filt_kernel(queue, (N,N), (WGPSIZE_1, WGPSIZE_2), f_1_tf_gpu.data, N)
    #nyq_filt_kernel(queue, (N,N), (WGPSIZE_1, WGPSIZE_2), f_2_tf_gpu.data, N)
    #nyq_filt_kernel(queue, (N,N), (WGPSIZE_1, WGPSIZE_2), f_3_tf_gpu.data, N)

    #zero_gpu(f_1_gpu)
    #zero_gpu(f_2_gpu)
    #zero_gpu(f_3_gpu)

    #add_gpu(f_1_gpu, u_1_tilde_gpu, 0.5, f_1_gpu)
    #add_gpu(f_2_gpu, u_2_tilde_gpu, 0.5, f_2_gpu)
    #add_gpu(f_3_gpu, u_3_tilde_gpu, 0.5, f_3_gpu)

    scale_gpu(u_1_tilde_gpu, 0.5, f_1_gpu)
    scale_gpu(u_2_tilde_gpu, 0.5, f_2_gpu)
    scale_gpu(u_3_tilde_gpu, 0.5, f_3_gpu)

    plan.execute(f_1_tf_gpu.data, inverse=True)
    plan.execute(f_2_tf_gpu.data, inverse=True)
    plan.execute(f_3_tf_gpu.data, inverse=True)
    
    real_gpu(f_1_tf_gpu, u_1_tilde_gpu)
    real_gpu(f_2_tf_gpu, u_2_tilde_gpu)
    real_gpu(f_3_tf_gpu, u_3_tilde_gpu)

    #print np.max(u_1_tilde_gpu.get())
    ##FE with projection step
    #copy_gpu(u_1_tilde_gpu, u_1_gpu)
    #copy_gpu(u_2_tilde_gpu, u_2_gpu)
    #copy_gpu(u_3_tilde_gpu, u_3_gpu)
    #return
    ############################################################

    ############################################################solve for u_soln
    ##change mu_hat for corrector
    #mu_hat = mu_min + mu_max

    #calc_lagF_gpu(X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, rr_lag_gpu, ip_s_lag_gpu, im_s_lag_gpu, ds, F_1_gpu, F_2_gpu, F_3_gpu)
    zero_gpu(F_1_gpu)
    zero_gpu(F_2_gpu)
    zero_gpu(F_3_gpu)
    calc_lagF_spec_new_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, CX_old_gpu.data, CX_max, N_pre_spec, k_spec, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    if (t_step < 200000):
        proj_tri_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, tri_ind_gpu.data, N_pre_spec, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_area_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, CT_gpu.data, CT_max, k_area, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #scale_gpu(F_1_gpu, da, F_1_gpu)
    #scale_gpu(F_2_gpu, da, F_2_gpu)
    #scale_gpu(F_3_gpu, da, F_3_gpu)
    calc_lagF_curv_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, CT_gpu.data, CT_max, k_curv, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    calc_lagF_hook_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, X_ref_1_gpu.data, X_ref_2_gpu.data, X_ref_3_gpu.data, CT_gpu.data, CT_max, k_bulk, k_shear, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_curv_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, CT_gpu.data, CT_max, k_curv, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_hook_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, X_ref_1_gpu.data, X_ref_2_gpu.data, X_ref_3_gpu.data, CT_gpu.data, CT_max, k_bulk, k_shear, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_wlc_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, fe_1_gpu.data, fe_2_gpu.data, CE_gpu.data, CE_max, N_pre_spec, k_wlc, L_cont, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_wlc_new_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, CX_old_gpu.data, CX_max, N_pre_spec, k_wlc, L_cont, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    #calc_lagF_spec_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, fe_1_gpu.data, fe_2_gpu.data, CE_gpu.data, CE_max, N_pre_spec, k_spec, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    copy_gpu(CX_gpu, CX_old_gpu)

    update_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, X_1_gpu, X_2_gpu, X_3_gpu, N1, N2, N3, dx1, dx2, dx3)
    #update_col_routine(queue, firstn1_col_gpu, nextn1_col_gpu, firstn2_col_gpu, nextn2_col_gpu, firstn3_col_gpu, nextn3_col_gpu, X_2_gpu, X_3_gpu, N2, N3, dx2, dx3)

    zero_gpu(u_1_gpu)
    zero_gpu(u_2_gpu)
    zero_gpu(u_3_gpu)
    #zero_gpu(precol_1)
    #zero_gpu(precol_2)
    #zero_gpu(precol_3)
    #zero_gpu(mu_1_gpu)
    #zero_gpu(mu_2_gpu)
    #zero_gpu(mu_3_gpu)
    #zero_gpu(rho_1_extra_gpu)
    #zero_gpu(rho_2_extra_gpu)
    #zero_gpu(rho_3_extra_gpu)

    spread_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_gpu, X_2_gpu, X_3_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, u_1_gpu, u_2_gpu, u_3_gpu)
    #spread_pre_col_routine(queue, firstn1_col_gpu, nextn1_col_gpu, firstn2_col_gpu, nextn2_col_gpu, firstn3_col_gpu, nextn3_col_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_gpu, X_2_gpu, X_3_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta)
    #sum_col_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), precol_1.data, precol_2.data, precol_3.data, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data)
    #spread_col_routine(queue, firstn1_col_gpu, nextn1_col_gpu, firstn2_col_gpu, nextn2_col_gpu, firstn3_col_gpu, nextn3_col_gpu, F_1_gpu, F_2_gpu, F_3_gpu, X_1_gpu, X_2_gpu, X_3_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, u_1_gpu, u_2_gpu, u_3_gpu)

    #zero_gpu(f_1_flat_gpu)
    #zero_gpu(f_2_flat_gpu)
    #zero_gpu(f_3_flat_gpu)
    ##f_1_manual = f_3_flat_gpu.get()
    #spread_routine2(queue, F_1_gpu, F_2_gpu, F_3_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N1, N2, N3, dx1, dx2, dx3, dtheta, f_1_flat_gpu, f_2_flat_gpu, f_3_flat_gpu)
    #copy_gpu(f_1_flat_gpu, f_1_gpu)
    #copy_gpu(f_2_flat_gpu, f_2_gpu)
    #copy_gpu(f_3_flat_gpu, f_3_gpu)

    add_gpu(u_3_gpu, body_gpu, body_f, u_3_gpu)
    #calc_f_gpu(t_step*dt, mu_0, rho_0, xx_1_stag_gpu, xx_2_stag_gpu, xx_3_stag_gpu, xx_1_c_gpu, xx_2_c_gpu, xx_3_c_gpu, u_1_gpu, u_2_gpu, u_3_gpu)

    #calc_coefs_kernel(queue, (N_tet, 1), (b_WGPSIZE_3,1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, Rho_gpu.data, Mu_gpu.data, dx1, dx2, dx3, N1, N2, N3, rho_1_extra_gpu.data, rho_2_extra_gpu.data, rho_3_extra_gpu.data, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data) 
    ##print 'av force is', np.mean(u_3_gpu.get())
    #zero_gpu(en_sum_gpu)
    #calc_rho_kernel(queue, (N_tet, 1), (b_WGPSIZE_3, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, Rho_gpu.data, en_sum_gpu.data)
    #rho_av = (en_sum_gpu.get().sum()+dx1*dx2*dx3*N1*N2*N3)/(dx1*dx2*dx3*N1*N2*N3)
    #rho_av = (rho_0*N1*N2*N3+rho_3_extra_gpu.get().sum())/(N1*N2*N3) 

    #add_gpu(u_3_gpu, rho_0-rho_av+rho_3_extra_gpu, -grav, u_3_gpu)

    #print 'av force is', np.mean(u_3_gpu.get())
    #add_gpu(rho_1_gpu, rho_1_extra_gpu, 1.0, rho_1_gpu)
    #add_gpu(rho_2_gpu, rho_2_extra_gpu, 1.0, rho_2_gpu)
    #add_gpu(rho_3_gpu, rho_3_extra_gpu, 1.0, rho_3_gpu)
    #print 'av force is', np.mean(u_3_gpu.get())

    #add_scalar_gpu(mu_1_gpu, -mu_bar, mu_1_gpu)
    #add_scalar_gpu(mu_2_gpu, -mu_bar, mu_2_gpu)
    #add_scalar_gpu(mu_3_gpu, -mu_bar, mu_3_gpu)
    #add_scalar_gpu(mu_1_gpu, mu_0-mu_hat, mu_1_gpu)
    #add_scalar_gpu(mu_2_gpu, mu_0-mu_hat, mu_2_gpu)
    #add_scalar_gpu(mu_3_gpu, mu_0-mu_hat, mu_3_gpu)
    #add_scalar_gpu(rho_1_gpu, -rho_bar, rho_1_gpu)
    #add_scalar_gpu(rho_2_gpu, -rho_bar, rho_2_gpu)
    #add_scalar_gpu(rho_3_gpu, -rho_bar, rho_3_gpu)
    #add_scalar_gpu(rho_1_gpu, rho_0-rho_hat, rho_1_gpu)
    #add_scalar_gpu(rho_2_gpu, rho_0-rho_hat, rho_2_gpu)
    #add_scalar_gpu(rho_3_gpu, rho_0-rho_hat, rho_3_gpu)

    #scale_gpu(rho_1_gpu, 0.5, rho_1_gpu)
    #scale_gpu(rho_2_gpu, 0.5, rho_2_gpu)
    #scale_gpu(rho_3_gpu, 0.5, rho_3_gpu)

    add_gpu(f_1_gpu, u_1_gpu, 0.5, f_1_gpu)
    add_gpu(f_2_gpu, u_2_gpu, 0.5, f_2_gpu)
    add_gpu(f_3_gpu, u_3_gpu, 0.5, f_3_gpu)

    #vc_laplace_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data) 

    #add_gpu(f_1_gpu, u_1_gpu, 0.5, f_1_gpu)
    #add_gpu(f_2_gpu, u_2_gpu, 0.5, f_2_gpu)
    #add_gpu(f_3_gpu, u_3_gpu, 0.5, f_3_gpu)

    #ss_conv_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data)
    ss_conv_fast_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data)
    #zero_gpu(u_1_gpu) #turn off convection
    #zero_gpu(u_2_gpu)
    #zero_gpu(u_3_gpu)

    add_gpu(f_1_gpu, u_1_gpu, -rho_hat*0.5, f_1_gpu)
    add_gpu(f_2_gpu, u_2_gpu, -rho_hat*0.5, f_2_gpu)
    add_gpu(f_3_gpu, u_3_gpu, -rho_hat*0.5, f_3_gpu)

    #ss_conv_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_o_gpu.data, u_2_o_gpu.data, u_3_o_gpu.data, dx1, dx2, dx3, N1, N2, N3, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data)
    #zero_gpu(mu_1_gpu) #turn off convection
    #zero_gpu(mu_2_gpu)
    #zero_gpu(mu_3_gpu)

    #add_gpu(u_1_gpu, mu_1_gpu, 1.0, u_1_gpu)
    #add_gpu(u_2_gpu, mu_2_gpu, 1.0, u_2_gpu)
    #add_gpu(u_3_gpu, mu_3_gpu, 1.0, u_3_gpu)

    #scale_gpu(u_1_gpu, 0.5, u_1_gpu)
    #scale_gpu(u_2_gpu, 0.5, u_2_gpu)
    #scale_gpu(u_3_gpu, 0.5, u_3_gpu)

    #dal_term_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_tilde_gpu.data, u_2_tilde_gpu.data, u_3_tilde_gpu.data, u_1_o_gpu.data, u_2_o_gpu.data, u_3_o_gpu.data, u_1_gpu.data, u_2_gpu.data,u_3_gpu.data, rho_1_gpu.data, rho_2_gpu.data, rho_3_gpu.data, dt, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data)

    #add_gpu(f_1_gpu, u_1_gpu, -1.0, f_1_gpu)
    #add_gpu(f_2_gpu, u_2_gpu, -1.0, f_2_gpu)
    #add_gpu(f_3_gpu, u_3_gpu, -1.0, f_3_gpu)

    div_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), f_1_gpu.data, f_2_gpu.data, f_3_gpu.data, dx1, dx2, dx3, N1, N2, N3, p_gpu.data)
    imag_gpu(p_gpu, p_tf_gpu)
    plan.execute(p_tf_gpu.data)

    L_adj_2_kernel(queue, (1,1), (1,1), L_tf_gpu.data)
    calc_p_gpu(p_tf_gpu, L_tf_gpu, p_tf_gpu)
    p_filt_kernel(queue, (1,1), (1,1), p_tf_gpu.data)
    plan.execute(p_tf_gpu.data, inverse=True)
    real_gpu(p_tf_gpu, p_gpu)

    grad_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), p_gpu.data, dx1, dx2, dx3, N1, N2, N3, u_1_gpu.data, u_2_gpu.data, u_3_gpu.data)

    add_gpu(f_1_gpu, u_1_gpu, -1, f_1_gpu)
    add_gpu(f_2_gpu, u_2_gpu, -1, f_2_gpu)
    add_gpu(f_3_gpu, u_3_gpu, -1, f_3_gpu)

    imag_gpu(f_1_gpu, f_1_tf_gpu)
    imag_gpu(f_2_gpu, f_2_tf_gpu)
    imag_gpu(f_3_gpu, f_3_tf_gpu)

    plan.execute(f_1_tf_gpu.data)
    plan.execute(f_2_tf_gpu.data)
    plan.execute(f_3_tf_gpu.data)

    L_adj_1_kernel(queue, (1,1), (1,1), L_tf_gpu.data)
    solve_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), u_1_tf_gpu.data, u_2_tf_gpu.data, u_3_tf_gpu.data, L_tf_gpu.data, f_1_tf_gpu.data, f_2_tf_gpu.data, f_3_tf_gpu.data, dt, rho_hat, mu_0/2.0, mu_hat/2.0, N1, N2, N3, f_1_tf_gpu.data, f_2_tf_gpu.data, f_3_tf_gpu.data)

    #nyq_filt_kernel(queue, (N,N), (WGPSIZE_1, WGPSIZE_2), f_1_tf_gpu.data, N)
    #nyq_filt_kernel(queue, (N,N), (WGPSIZE_1, WGPSIZE_2), f_2_tf_gpu.data, N)
    #nyq_filt_kernel(queue, (N,N), (WGPSIZE_1, WGPSIZE_2), f_3_tf_gpu.data, N)

    plan.execute(f_1_tf_gpu.data, inverse=True)
    plan.execute(f_2_tf_gpu.data, inverse=True)
    plan.execute(f_3_tf_gpu.data, inverse=True)
    
    real_gpu(f_1_tf_gpu, u_1_gpu)
    real_gpu(f_2_tf_gpu, u_2_gpu)
    real_gpu(f_3_tf_gpu, u_3_gpu)

    #zero_gpu(F_1_gpu)
    #zero_gpu(F_2_gpu)
    #zero_gpu(F_3_gpu)

    interp_kernel(queue, (b_q, 1), (b_WGPSIZE_2, 1), u_1_gpu.data, u_2_gpu.data, u_3_gpu.data, X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, N1, N2, N3, dx1, dx2, dx3, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data)
    add_gpu(U_1_gpu, F_1_gpu, 1, U_1_gpu)
    add_gpu(U_2_gpu, F_2_gpu, 1, U_2_gpu)
    add_gpu(U_3_gpu, F_3_gpu, 1, U_3_gpu)

    if INNIE:
        zero_gpu(en_gpu)
        calc_total_area_kernel(queue, (1, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, k_area, N_tri, en_gpu.data) 
        ar = en_gpu.get()[0]
        zero_gpu(en_gpu)
        calc_energy_volume_kernel(queue, (1, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, N_tri, en_gpu.data) 
        vol = np.abs(en_gpu.get()[0])
        s_0 = 0.0
        if ((vol-vol_t)/vol_t > 0.001):
            s_0 = s_00 
        zero_gpu(F_1_gpu)
        zero_gpu(F_2_gpu)
        zero_gpu(F_3_gpu)
        calc_nrml_kernel(queue, (N_r, 1), (b_WGPSIZE_1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, CT_gpu.data, CT_max, k_area, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data, 0)
        calc_nrml_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, TV_spec_1_gpu.data, TV_spec_2_gpu.data, TV_spec_3_gpu.data, A_0_gpu.data, CT_spec_gpu.data, CT_max, k_area, F_1_gpu.data, F_2_gpu.data, F_3_gpu.data, N_pre_spec)
        add_gpu(U_1_gpu, F_1_gpu, -s_0, U_1_gpu)
        add_gpu(U_2_gpu, F_2_gpu, -s_0, U_2_gpu)
        add_gpu(U_3_gpu, F_3_gpu, -s_0, U_3_gpu)


    #if (t_step < 5000):
    #    proj_sphere_kernel(queue, (b_q, 1), (b_WGPSIZE_2, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, N_pre_spec, U_1_gpu.data, U_2_gpu.data, U_3_gpu.data)

    add_gpu(X_1_gpu, U_1_gpu, dt/2., X_1_gpu)
    add_gpu(X_2_gpu, U_2_gpu, dt/2., X_2_gpu)
    add_gpu(X_3_gpu, U_3_gpu, dt/2., X_3_gpu)

    #update_routine(queue, firstn1_gpu, nextn1_gpu, firstn2_gpu, nextn2_gpu, firstn3_gpu, nextn3_gpu, X_1_gpu, X_2_gpu, X_3_gpu, N1, N2, N3, dx1, dx2, dx3)
    if SAVE:
        zero_gpu(mu_1_gpu)
        zero_gpu(mu_2_gpu)
        zero_gpu(mu_3_gpu)
        zero_gpu(rho_1_gpu)
        zero_gpu(rho_2_gpu)
        zero_gpu(rho_3_gpu)
        calc_coefs_kernel(queue, (N_tet, 1), (b_WGPSIZE_3,1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TW_1_gpu.data, TW_2_gpu.data, TW_3_gpu.data, TW_4_gpu.data, Rho_gpu.data, Mu_gpu.data, dx1, dx2, dx3, N1, N2, N3, rho_1_gpu.data, rho_2_gpu.data, rho_3_gpu.data, mu_1_gpu.data, mu_2_gpu.data, mu_3_gpu.data) 
        add_scalar_gpu(rho_1_gpu, rho_0, rho_1_gpu)
        add_scalar_gpu(rho_2_gpu, rho_0, rho_2_gpu)
        add_scalar_gpu(rho_3_gpu, rho_0, rho_3_gpu)
        add_scalar_gpu(mu_1_gpu, mu_0, mu_1_gpu)
        add_scalar_gpu(mu_2_gpu, mu_0, mu_2_gpu)
        add_scalar_gpu(mu_3_gpu, mu_0, mu_3_gpu)
    ##############################################################
    return

def err(u_1, u_2, u_3, u_1_o, u_2_o, u_3_o):
    global dx
    NN_o = u_1_o.shape[0]
    errinf1 = 0.
    errinf2 = 0.
    errinf3 = 0.
    err11 = 0.
    err12 = 0.
    err13 = 0.
    err21 = 0.
    err22 = 0.
    err23 = 0.

    for i in range(0,NN_o):
        for j in range(0,NN_o):
            for k in range(0,NN_o):
                if (np.abs(u_1_o[k,i,j]-0.25*(u_1[2*k,2*i,2*j]+u_1[2*k,2*i+1,2*j]+u_1[2*k+1,2*i,2*j]+u_1[2*k+1,2*i+1,2*j]))>errinf1):
                    errinf1 = np.abs(u_1_o[k,i,j]-0.25*(u_1[2*k,2*i,2*j]+u_1[2*k,2*i+1,2*j]+u_1[2*k+1,2*i,2*j]+u_1[2*k+1,2*i+1,2*j])) 
                if (np.abs(u_2_o[k,i,j]-0.25*(u_2[2*k,2*i,2*j]+u_2[2*k,2*i,2*j+1]+u_2[2*k+1,2*i,2*j]+u_2[2*k+1,2*i,2*j+1]))>errinf2):
                    errinf2 = np.abs(u_2_o[k,i,j]-0.25*(u_2[2*k,2*i,2*j]+u_2[2*k,2*i,2*j+1]+u_2[2*k+1,2*i,2*j]+u_2[2*k+1,2*i,2*j+1])) 
                if (np.abs(u_3_o[k,i,j]-0.25*(u_3[2*k,2*i,2*j]+u_3[2*k,2*i+1,2*j]+u_3[2*k,2*i,2*j+1]+u_3[2*k,2*i+1,2*j+1]))>errinf3):
                    errinf3 = np.abs(u_3_o[k,i,j]-0.25*(u_3[2*k,2*i,2*j]+u_3[2*k,2*i+1,2*j]+u_3[2*k,2*i,2*j+1]+u_3[2*k,2*i+1,2*j+1])) 
                err21 += np.abs(u_1_o[k,i,j]-0.25*(u_1[2*k,2*i,2*j]+u_1[2*k,2*i+1,2*j]+u_1[2*k+1,2*i,2*j]+u_1[2*k+1,2*i+1,2*j]))**2 
                err22 += np.abs(u_2_o[k,i,j]-0.25*(u_2[2*k,2*i,2*j]+u_2[2*k,2*i,2*j+1]+u_2[2*k+1,2*i,2*j]+u_2[2*k+1,2*i,2*j+1]))**2 
                err23 += np.abs(u_3_o[k,i,j]-0.25*(u_3[2*k,2*i,2*j]+u_3[2*k,2*i+1,2*j]+u_3[2*k,2*i,2*j+1]+u_3[2*k,2*i+1,2*j+1]))**2 
                err11 += np.abs(u_1_o[k,i,j]-0.25*(u_1[2*k,2*i,2*j]+u_1[2*k,2*i+1,2*j]+u_1[2*k+1,2*i,2*j]+u_1[2*k+1,2*i+1,2*j])) 
                err12 += np.abs(u_2_o[k,i,j]-0.25*(u_2[2*k,2*i,2*j]+u_2[2*k,2*i,2*j+1]+u_2[2*k+1,2*i,2*j]+u_2[2*k+1,2*i,2*j+1])) 
                err13 += np.abs(u_3_o[k,i,j]-0.25*(u_3[2*k,2*i,2*j]+u_3[2*k,2*i+1,2*j]+u_3[2*k,2*i,2*j+1]+u_3[2*k,2*i+1,2*j+1])) 

    err21 = np.sqrt(err21*dx**3/8)
    err22 = np.sqrt(err22*dx**3/8)
    err23 = np.sqrt(err23*dx**3/8)
    err11 = (dx**3/8)*err11
    err12 = (dx**3/8)*err12
    err13 = (dx**3/8)*err13

    return errinf1, errinf2, errinf3, err11, err12, err13, err21, err22, err23 

def err_ex(clock_max, u_1, u_2, u_3):
    global dx, dt
    x_stag = np.arange(-0.5, 0.5, dx)
    xx_1_stag = np.tile(x_stag, (N, N, 1))
    xx_2_stag = np.tile(x_stag.reshape(N,1), (N, 1, N))
    xx_3_stag = np.tile(x_stag.reshape(N,1,1), (1, N, N))

    x_c = np.arange(-0.5+dx/2, 0.5+dx/2, dx)
    xx_1_c = np.tile(x_c, (N, N, 1))
    xx_2_c = np.tile(x_c.reshape(N,1), (N, 1, N))
    xx_3_c = np.tile(x_c.reshape(N,1,1), (1, N, N))
    
    u_1_ex = 2*np.cos(2*pi*xx_1_stag)*np.sin(4*pi*xx_2_c)*np.sin(clock_max*dt)*np.sin(2*pi*xx_3_c)
    u_2_ex = -np.sin(2*pi*xx_1_c)*np.cos(4*pi*xx_2_stag)*np.sin(clock_max*dt)*np.sin(2*pi*xx_3_c)
    u_3_ex = np.cos(2*pi*xx_1_c)*np.sin(4*pi*xx_2_c)*np.cos(clock_max*dt)

    errinf1 = np.abs(u_1-u_1_ex).max()
    errinf2 = np.abs(u_2-u_2_ex).max()
    errinf3 = np.abs(u_3-u_3_ex).max()
    err11 = np.sum(np.abs(u_1-u_1_ex))*dx**3
    err12 = np.sum(np.abs(u_2-u_2_ex))*dx**3
    err13 = np.sum(np.abs(u_3-u_3_ex))*dx**3
    err21 = np.sqrt(np.sum(np.abs(u_1-u_1_ex)**2*dx**3))
    err22 = np.sqrt(np.sum(np.abs(u_2-u_2_ex)**2*dx**3))
    err23 = np.sqrt(np.sum(np.abs(u_3-u_3_ex)**2*dx**3))

    return errinf1, errinf2, errinf3, err11, err12, err13, err21, err22, err23

#platform = cl.get_platforms()
#my_gpu_devices = platform[0].get_devices(cl.device_type.GPU)
#ctx = cl.Context([my_gpu_devices[0]]) 
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)

calc_lagF_gpu = ElementwiseKernel(ctx,
	"float *X_1, float *X_2, float *X_3,"
	"float *rr_lag, unsigned *ip_s_lag, unsigned *im_s_lag, " 
	"float ds, "
	"float *F_1, float *F_2, float *F_3",
	#"F_1[i] = 1./(ds*ds)*(1.+sin(2.*pi*rr_lag[i]-pi/2.))"
	#   "*(X_1[ip_s_lag[i]]-2.*X_1[i]+X_1[im_s_lag[i]]); "
	#"F_2[i] = 1./(ds*ds)*(1.+sin(2.*pi*rr_lag[i]-pi/2.))"
	#   "*(X_2[ip_s_lag[i]]-2.*X_2[i]+X_2[im_s_lag[i]]);"
	#"F_3[i] = 1./(ds*ds)*(1.+sin(2.*pi*rr_lag[i]-pi/2.))"
	#   "*(X_3[ip_s_lag[i]]-2.*X_3[i]+X_3[im_s_lag[i]])",
	#"F_1[i] = 1./(2*ds)"
	#   "*(X_1[ip_s_lag[i]]-X_1[im_s_lag[i]]); "
	#"F_2[i] = 1./(2*ds)"
	#   "*(X_2[ip_s_lag[i]]-X_2[im_s_lag[i]]);"
	#"F_3[i] = 1./(2*ds)"
	#   "*(X_3[ip_s_lag[i]]-X_3[im_s_lag[i]])",
	#"F_1[i] = 1./(ds*ds)*(X_1[ip_s_lag[i]]-2.*X_1[i]+X_1[im_s_lag[i]]); "
	#"F_2[i] = 1./(ds*ds)*(X_2[ip_s_lag[i]]-2.*X_2[i]+X_2[im_s_lag[i]]) ",
        "F_1[i] = 0.;"
        "F_2[i] = 0.;"
        "F_3[i] = 0.",
	"calc_lagF_gpu",
	preamble="""
	#define pi (float)3.141592653589793
	""")

calc_f_gpu = ElementwiseKernel(ctx,
        "float t, float mu, float rho, "
        "float *xx_1_stag, float *xx_2_stag, float *xx_3_stag,"
        "float *xx_1_c, float *xx_2_c, float *xx_3_c,"
        "float *f_1, float *f_2, float *f_3",
        "f_1[i] = rho*2*cos(2*pi*xx_1_stag[i])*sin(4*pi*xx_2_c[i])*sin(2*pi*xx_3_c[i])*cos(t)"
           "+2*pi*cos(2*pi*xx_1_stag[i])*sin(2*pi*xx_2_c[i])*cos(2*pi*xx_3_c[i])*cos(t)"
           "+mu*48*pi*pi*cos(2*pi*xx_1_stag[i])*sin(4*pi*xx_2_c[i])*sin(2*pi*xx_3_c[i])*sin(t)"
           "-rho*4*pi*sin(t)*sin(t)*sin(4*pi*xx_1_stag[i])*sin(2*pi*xx_3_c[i])*sin(2*pi*xx_3_c[i])"
           "+rho*4*pi*sin(t)*cos(t)*cos(2*pi*xx_1_stag[i])*cos(2*pi*xx_1_stag[i])*sin(4*pi*xx_2_c[i])"
           "*sin(4*pi*xx_2_c[i])*cos(2*pi*xx_3_c[i]);"
        "f_2[i] = -rho*sin(2*pi*xx_1_c[i])*cos(4*pi*xx_2_stag[i])*sin(2*pi*xx_3_c[i])*cos(t)"
           "+2*pi*sin(2*pi*xx_1_c[i])*cos(2*pi*xx_2_stag[i])*cos(2*pi*xx_3_c[i])*cos(t)"
           "-mu*24*pi*pi*sin(2*pi*xx_1_c[i])*cos(4*pi*xx_2_stag[i])*sin(2*pi*xx_3_c[i])*sin(t)"
           "-rho*2*pi*sin(t)*sin(t)*sin(8*pi*xx_2_stag[i])*sin(2*pi*xx_3_c[i])*sin(2*pi*xx_3_c[i])"
           "-rho*0.5*pi*sin(t)*cos(t)*sin(4*pi*xx_1_c[i])*sin(8*pi*xx_2_stag[i])"
           "*cos(2*pi*xx_3_c[i]);"
        "f_3[i] = -rho*cos(2*pi*xx_1_c[i])*sin(4*pi*xx_2_c[i])*sin(t)"
           "-2*pi*sin(2*pi*xx_1_c[i])*sin(2*pi*xx_2_c[i])*sin(2*pi*xx_3_stag[i])*cos(t)"
           "+mu*20*pi*pi*cos(2*pi*xx_1_c[i])*sin(4*pi*xx_2_c[i])*cos(t)"
           "-rho*2*pi*cos(t)*sin(t)*sin(4*pi*xx_1_c[i])*sin(2*pi*xx_3_stag[i])",
        "calc_f_gpu",
        preamble="""
        #define pi (float)3.141592653589793
        """)

complex_mult_gpu = ElementwiseKernel(ctx,
	"float2 *u_1, float2 *u_2, float2 *f",
	"f[i] = complex_mul(u_1[i], u_2[i])",
	"complex_mult_gpu",
	preamble="""
	#define complex_ctr(x, y) (float2)(x, y)
	#define complex_mul(a, b) complex_ctr(-(a).y*(b).y+(a).x*(b).x, (a).y*(b).x+(a).x*(b).y)
	""")

mult_gpu = ElementwiseKernel(ctx,
	"float *u_1, float *u_2, float *f",
	"f[i] = u_1[i]*u_2[i]",
	"mult_gpu")

add_gpu = ElementwiseKernel(ctx,
	"float *u_1, float *u_2, float a, float *f",
	"f[i] = u_1[i]+a*u_2[i]",
	"add_gpu")

add_scalar_gpu = ElementwiseKernel(ctx,
	"float *u, float a, float *f",
	"f[i] = u[i]+a",
	"add_scalar_gpu")
    
set_int_gpu = ElementwiseKernel(ctx,
	"int a, int *f",
	"f[i] = a",
	"set_int_gpu")

copy_gpu = ElementwiseKernel(ctx,
	"float *u, float *f",
	"f[i] = u[i]",
	"copy_gpu")

copy_int_gpu = ElementwiseKernel(ctx,
	"unsigned *u, unsigned *f",
	"f[i] = u[i]",
	"copy_int_gpu")

scale_gpu = ElementwiseKernel(ctx,
	"float *u, float a, float *f",
	"f[i] = a*u[i]",
	"scale_gpu")

real_gpu = ElementwiseKernel(ctx,
	"float2 *x, float *z",
	"z[i] = x[i].x",
	"real_gpu")

imag_gpu = ElementwiseKernel(ctx,
	"float *x, float2 *z",
	"z[i].x = x[i];"
	"z[i].y = 0",
	"imag_gpu")

zero_gpu = ElementwiseKernel(ctx,
	"float *x",
	"x[i] = 0",
	"zero_gpu")
 
null_imag_gpu = ElementwiseKernel(ctx,
	"float2 *x, float2 *z",
	"z[i].x = x[i].x;"
	"z[i].y = 0",
	"null_imag_gpu")

test_meml_gpu = ElementwiseKernel(ctx,
	"float *x",
        #"printf('index is %i', i);"
        #"printf('entry is %g', x[i])",
        "x[i]=0.0",
	"test_meml_gpu",
        preamble="""
        //#pragma OPENCL EXTENSION cl_amd_printf : enable
        """)

calc_p_gpu = ElementwiseKernel(ctx,
	"float2 *w_tf, float2 *L_tf, float2 *p_tf",
	"p_tf[i] = complex_div(w_tf[i], L_tf[i])",
	"calc_p_gpu",
	preamble="""
	#define complex_ctr(x, y) (float2)(x, y)
	#define complex_div(a, b) 1/((b).x*(b).x+(b).y*(b).y)*complex_ctr((a).y*(b).y+(a).x*(b).x,(a).y*(b).x-(a).x*(b).y)
	""")

solve_prg = cl.Program(ctx, """
    //#pragma OPENCL EXTENSION cl_amd_printf : enable
    #define complex_ctr(x, y) (float2)(x, y)
    #define complex_mul(a, b) complex_ctr(-(a).y*(b).y+(a).x*(b).x, (a).y*(b).x+(a).x*(b).y)
    #define complex_div(a, b) 1/((b).x*(b).x+(b).y*(b).y)*complex_ctr((a).y*(b).y+(a).x*(b).x,(a).y*(b).x-(a).x*(b).y)
    __kernel void test_meml(__global const *x, const unsigned N1, const unsigned N2, const unsigned N3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(0);
      unsigned k = get_global_id(2);
      unsigned base = i + N1*j + N1*N2*k;
      //printf('%i', base);
      //printf('%g', x[base]);
    }
    __kernel void solve(__global const float2 *u_1_tf, __global const float2 *u_2_tf, 
    __global const float2 *u_3_tf, __global const float2 *L_tf,
    __global const float2 *f_1_tf, __global const float2 *f_2_tf, 
    __global const float2 *f_3_tf, const float dt, 
    const float rho, const float mu_1, const float mu_2, const unsigned N1, const unsigned N2, const unsigned N3,
    __global float2 *u_1_tf_tilde, __global float2 *u_2_tf_tilde, __global float2 *u_3_tf_tilde)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);
      unsigned base = i + N1*j + N1*N2*k;
      float2 m;
      m.x = 1.0+mu_1*dt/rho*L_tf[base].x; 
      m.y = mu_1*dt/rho*L_tf[base].y; 
      //debugging
      //m.x = 1.0; 
      //m.y = 0.0; 
      //for FE step
      //m.x = 1.0+mu*dt/(rho)*L_tf[base].x; 
      //m.y = mu*dt/(rho)*L_tf[base].y; 
      float2 rhs_1 = complex_mul(m, u_1_tf[base])+dt/rho*f_1_tf[base];
      float2 rhs_2 = complex_mul(m, u_2_tf[base])+dt/rho*f_2_tf[base];
      float2 rhs_3 = complex_mul(m, u_3_tf[base])+dt/rho*f_3_tf[base];
      float2 lhs;
      lhs.x = 1.0-mu_2*dt/rho*L_tf[base].x;
      lhs.y = -mu_2*dt/rho*L_tf[base].y;
      //for FE step
      //lhs.x = 1.0;
      //lhs.y = 0.0; 
      u_1_tf_tilde[base] = complex_div(rhs_1, lhs);
      u_2_tf_tilde[base] = complex_div(rhs_2, lhs);
      u_3_tf_tilde[base] = complex_div(rhs_3, lhs);
    }
    __kernel void dal_term(__global const float *u_1, __global const float *u_2, __global const float *u_3, __global const float *u_1_o, __global const float *u_2_o, __global const float *u_3_o, __global const float *ss_1, __global const float *ss_2, __global const float *ss_3, __global const float *rho_1, __global const float *rho_2, __global const float *rho_3,
    const float dt, const unsigned N1, const unsigned N2, const unsigned N3,
    __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);
      unsigned base = i + N1*j + N1*N2*k;
      f_1[base] = rho_1[base]*((u_1[base]-u_1_o[base])/dt+ss_1[base]);
      f_2[base] = rho_2[base]*((u_2[base]-u_2_o[base])/dt+ss_2[base]);
      f_3[base] = rho_3[base]*((u_3[base]-u_3_o[base])/dt+ss_3[base]);
    }
    __kernel void vc_laplace(__global const float *u_1,
    __global const float *u_2,
    __global const float *u_3,
    __global const float *mu_1,
    __global const float *mu_2, __global const float *mu_3,
    const float dx1, const float dx2, const float dx3,
    const unsigned N1, const unsigned N2, const unsigned N3,
    __global float *V_1, __global float *V_2, __global float *V_3)
    {
    unsigned i = get_global_id(0);
    unsigned j = get_global_id(1);
    unsigned k = get_global_id(2);
    unsigned base = i + N1*j + N1*N2*k;
    unsigned base1 = (i+1 & N1-1) + N1*j + N1*N2*k;
    unsigned base2 = (i-1 & N1-1) + N1*j + N1*N2*k;
    unsigned base3 = i + N1*(j+1 & N2-1) + N1*N2*k;
    unsigned base4 = i + N1*(j-1 & N2-1) + N1*N2*k;
    unsigned base5 = (i-1 & N1-1) + N1*(j+1 & N2-1) + N1*N2*k;
    unsigned base6 = (i+1 & N1-1) + N1*(j-1 & N2-1) + N1*N2*k;
    unsigned base7 = i + N1*j + N1*N2*(k+1 & N3-1);
    unsigned base8 = i + N1*j + N1*N2*(k-1 & N3-1);
    unsigned base9 = (i-1 & N1-1) + N1*j + N1*N2*(k+1 & N3-1);
    unsigned base10 = (i+1 & N1-1) + N1*j + N1*N2*(k-1 & N3-1);
    unsigned base11 = i + N1*(j-1 & N2-1) + N1*N2*(k+1 & N3-1);
    unsigned base12 = i + N1*(j+1 & N2-1) + N1*N2*(k-1 & N3-1);

    V_1[base] = 1.0/(dx1*dx1)*(2.0*(0.5*(mu_1[base]+mu_1[base1])*(u_1[base1]-u_1[base])
               -0.5*(mu_1[base]+mu_1[base2])*(u_1[base]-u_1[base2])))
               +1.0/(dx2*dx2)*(0.5*(mu_1[base3]+mu_1[base])*(u_1[base3]-u_1[base])
               -0.5*(mu_1[base]+mu_1[base4])*(u_1[base]-u_1[base4])) 
               +1.0/(dx1*dx2)*(0.5*(mu_1[base3]+mu_1[base])*(u_2[base3]-u_2[base5])
               -0.5*(mu_1[base]+mu_1[base4])*(u_2[base]-u_2[base2]))
               +1.0/(dx3*dx3)*(0.5*(mu_1[base]+mu_1[base7])*(u_1[base7]-u_1[base])
               -0.5*(mu_1[base]+mu_1[base8])*(u_1[base]-u_1[base8]))
               +1.0/(dx1*dx3)*(0.5*(mu_1[base]+mu_1[base7])*(u_3[base7]-u_3[base9])
               -0.5*(mu_1[base]+mu_1[base8])*(u_3[base]-u_3[base2]));

    V_2[base] = 1.0/(dx1*dx1)*(0.5*(mu_2[base]+mu_2[base1])*(u_2[base1]-u_2[base])
               -0.5*(mu_2[base]+mu_2[base2])*(u_2[base]-u_2[base2]))
               +1.0/(dx1*dx2)*(0.5*(mu_2[base]+mu_2[base1])*(u_1[base1]-u_1[base6])
               -0.5*(mu_2[base]+mu_2[base2])*(u_1[base]-u_1[base4]))
               +1.0/(dx2*dx2)*(2*(0.5*(mu_2[base]+mu_2[base3])*(u_2[base3]-u_2[base])
               -0.5*(mu_2[base]+mu_2[base4])*(u_2[base]-u_2[base4])))
               +1.0/(dx3*dx3)*(0.5*(mu_2[base]+mu_2[base7])*(u_2[base7]-u_2[base])
               -0.5*(mu_2[base]+mu_2[base8])*(u_2[base]-u_2[base8]))
               +1.0/(dx2*dx3)*(0.5*(mu_2[base]+mu_2[base7])*(u_3[base7]-u_3[base11])
               -0.5*(mu_2[base]+mu_2[base8])*(u_3[base]-u_3[base4]));

    V_3[base] = 1.0/(dx1*dx1)*(0.5*(mu_3[base]+mu_3[base1])*(u_3[base1]-u_3[base])
                -0.5*(mu_3[base]+mu_3[base2])*(u_3[base]-u_3[base2]))
                +1.0/(dx1*dx3)*(0.5*(mu_3[base]+mu_3[base1])*(u_1[base1]-u_1[base10])
                -0.5*(mu_3[base]+mu_3[base2])*(u_1[base]-u_1[base8]))
                +1.0/(dx2*dx2)*(0.5*(mu_3[base]+mu_3[base3])*(u_3[base3]-u_3[base])
                -0.5*(mu_3[base]+mu_3[base4])*(u_3[base]-u_3[base4]))
                +1.0/(dx2*dx3)*(0.5*(mu_3[base]+mu_3[base3])*(u_2[base3]-u_2[base12])
                -0.5*(mu_3[base]+mu_3[base4])*(u_2[base]-u_2[base8]))
                +1.0/(dx3*dx3)*(2.0*(0.5*(mu_3[base]+mu_3[base7])*(u_3[base7]-u_3[base])
                -0.5*(mu_3[base]+mu_3[base8])*(u_3[base]-u_3[base8])));

    }
    """).build()

prg = cl.Program(ctx, """
    //#pragma OPENCL EXTENSION cl_amd_printf : enable
    __kernel void p_filt(__global float2 *u)
    {
      u[0].x = 0.0;
      u[0].y = 0.0;
    }
    __kernel void L_adj_1(__global float2 *L_tf)
    {
      L_tf[0].x = 0.0;
      L_tf[0].y = 0.0;
    }
    __kernel void L_adj_2(__global float2 *L_tf)
    {
      L_tf[0].x = 1.0;
      L_tf[0].y = 0.0;
    }
    __kernel void nyq_filt(__global float2 *u, const unsigned N1, const unsigned N2, const unsigned N3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned base = N1/2 + N1*i + N1*N2*j; 
      unsigned base1 = i + N1*N2/2 + N1*N2*j; 
      unsigned base2 = i + N1*j + N1*N2*N3/2; 
   
      u[base].x = 0.0;
      u[base].y = 0.0;
      u[base1].x = 0.0;
      u[base1].y = 0.0;
      u[base2].x = 0.0;
      u[base2].y = 0.0;
    }
    __kernel void div(__global const float *u_1,
    __global const float *u_2, __global const float *u_3, 
    const float dx1, const float dx2, const float dx3,
    const unsigned N1, const unsigned N2, const unsigned N3, __global float *f)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);
      //f[i,j] = 1/dx*(u_1[i_2[i,j],ip_1[i,j]]-u_1[i,j]+u_2[ip_2[i,j],i_1[i,j]]-u_2[i,j];
      unsigned base = i + N1*j + N1*N2*k;
      unsigned base1 = (i+1 & N1-1)+N1*j + N1*N2*k;
      unsigned base2 = i+N1*(j+1 & N2-1) + N1*N2*k;
      unsigned base3 = i + N1*j + N1*N2*(k+1 & N3-1);
      f[base] = 1.0/dx1*(u_1[base1]-u_1[base])+
                1.0/dx2*(u_2[base2]-u_2[base])+
                1.0/dx3*(u_3[base3]-u_3[base]);
    }
    __kernel void grad(__global const float *phi,
    const float dx1, const float dx2, const float dx3,
    const unsigned N1, const unsigned N2, const unsigned N3,
    __global float *g_1, __global float *g_2, __global float *g_3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);
      //grad_1 = 1/dx*(phi[i_2,i_1]-phi[i_2,im_1])
      //grad_2 = 1/dx*(phi[i_2,i_1]-phi[im_2,i_1])
      unsigned base = i + N1*j + N1*N2*k;
      unsigned base1 = (i-1 & N1-1)+N1*j + N1*N2*k;
      unsigned base2 = i+N1*(j-1 & N2-1) + N1*N2*k;
      unsigned base3 = i + N1*j + N1*N2*(k-1 & N3-1);
      g_1[base] = 1/dx1*(phi[base]-phi[base1]);
      g_2[base] = 1/dx2*(phi[base]-phi[base2]);
      g_3[base] = 1/dx3*(phi[base]-phi[base3]);
    }
    __kernel void ss_conv_fast(__global const float *u_1,
    __global const float *u_2, __global const float *u_3,
    const float dx1, const float dx2, const float dx3,
    const unsigned N1, const unsigned N2, const unsigned N3,
    __global float *S_1, __global float *S_2, __global float *S_3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);
      //Compute S = div(UU)
      unsigned base = i+N1*j+N1*N2*k;
      unsigned base1 = (i-1 & N1-1)+N1*j+N1*N2*k;
      unsigned base2 = (i+1 & N1-1)+N1*j+N1*N2*k;
      unsigned base3 = i+N1*(j-1 & N2-1)+N1*N2*k;
      unsigned base4 = i+N1*(j+1 & N2-1)+N1*N2*k;
      unsigned base5 = (i-1 & N1-1)+N1*(j+1 & N2-1)+N1*N2*k;
      unsigned base6 = (i+1 & N1-1)+N1*(j-1 & N2-1)+N1*N2*k;
      unsigned base7 = i+N1*j+N1*N2*(k-1 & N3-1);
      unsigned base8 = i+N1*j+N1*N2*(k+1 & N3-1);
      unsigned base9 = (i-1 & N1-1)+N1*j+N1*N2*(k+1 & N3-1);
      unsigned base10 = i+N1*(j-1 & N2-1)+N1*N2*(k+1 & N3-1);
      unsigned base11 = (i+1 & N1-1)+N1*j+N1*N2*(k-1 & N3-1);
      unsigned base12 = i+N1*(j+1 & N2-1)+N1*N2*(k-1 & N3-1);
      float D_x, D_y, D_z, A_x, A_y, A_z, D, A;

      float u1b, u1b1, u1b2, u1b3, u1b4, u1b6, u1b7, u1b8, u1b11;
      float u2b, u2b1, u2b2, u2b3, u2b4, u2b5, u2b7, u2b8, u2b12;
      float u3b, u3b1, u3b2, u3b3, u3b4, u3b7, u3b8, u3b9, u3b10;

      u1b1 = u_1[base1];
      u1b = u_1[base];
      u1b2 = u_1[base2];
      u1b3 = u_1[base3];
      u1b6 = u_1[base6];
      u1b4 = u_1[base4];
      u1b7 = u_1[base7];
      u1b8 = u_1[base8];
      u1b11 = u_1[base11];
      
      u2b1 = u_2[base1];
      u2b = u_2[base];
      u2b2 = u_2[base2];
      u2b3 = u_2[base3];
      u2b5 = u_2[base5];
      u2b4 = u_2[base4];
      u2b7 = u_2[base7];
      u2b8 = u_2[base8];
      u2b12 = u_2[base12];
      
      u3b1 = u_3[base1];
      u3b = u_3[base];
      u3b2 = u_3[base2];
      u3b3 = u_3[base3];
      u3b4 = u_3[base4];
      u3b7 = u_3[base7];
      u3b8 = u_3[base8];
      u3b9 = u_3[base9];
      u3b10 = u_3[base10];
      
      D_x = (0.25/dx1)*(
          (u1b2+u1b)*(u1b2+u1b)-
          (u1b+u1b1)*(u1b+u1b1));
      D_y = (0.25/dx2)*(
          (u2b4+u2b5)*(u1b4+u1b)-
          (u2b+u2b1)*(u1b+u1b3));
      D_z = (0.25/dx3)*(
          (u3b8+u3b9)*(u1b8+u1b)-
          (u3b+u3b1)*(u1b+u1b7));
      D = D_x + D_y + D_z;
      S_1[base] = D;
      D_x = (0.25/dx1)*(
          (u1b2+u1b6)*(u2b2+u2b)-
          (u1b+u1b3)*(u2b+u2b1));
      D_y = (0.25/dx2)*(
          (u2b4+u2b)*(u2b4+u2b)-
          (u2b+u2b3)*(u2b+u2b3));
      D_z = (0.25/dx3)*(
          (u3b8+u3b10)*(u2b8+u2b)-
          (u3b+u3b3)*(u2b+u2b7));
      D = D_x + D_y + D_z;
      S_2[base] = D;
      D_x = (0.25/dx1)*(
          (u1b2+u1b11)*(u3b2+u3b)-
          (u1b+u1b7)*(u3b+u3b1));
      D_y = (0.25/dx2)*(
          (u2b4+u2b12)*(u3b4+u3b)-
          (u2b+u2b7)*(u3b+u3b3));
      D_z = (0.25/dx3)*(
          (u3b8+u3b)*(u3b8+u3b)-
          (u3b+u3b7)*(u3b+u3b7));
      D = D_x + D_y + D_z;
      S_3[base] = D;
    }
    __kernel void ss_conv(__global const float *u_1,
    __global const float *u_2, __global const float *u_3,
    const float dx1, const float dx2, const float dx3,
    const unsigned N1, const unsigned N2, const unsigned N3,
    __global float *S_1, __global float *S_2, __global float *S_3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);
      //Compute S = 0.5*(div(UU) + (U*grad)U).
      unsigned base = i+N1*j+N1*N2*k;
      unsigned base1 = (i-1 & N1-1)+N1*j+N1*N2*k;
      unsigned base2 = (i+1 & N1-1)+N1*j+N1*N2*k;
      unsigned base3 = i+N1*(j-1 & N2-1)+N1*N2*k;
      unsigned base4 = i+N1*(j+1 & N2-1)+N1*N2*k;
      unsigned base5 = (i-1 & N1-1)+N1*(j+1 & N2-1)+N1*N2*k;
      unsigned base6 = (i+1 & N1-1)+N1*(j-1 & N2-1)+N1*N2*k;
      unsigned base7 = i+N1*j+N1*N2*(k-1 & N3-1);
      unsigned base8 = i+N1*j+N1*N2*(k+1 & N3-1);
      unsigned base9 = (i-1 & N1-1)+N1*j+N1*N2*(k+1 & N3-1);
      unsigned base10 = i+N1*(j-1 & N2-1)+N1*N2*(k+1 & N3-1);
      unsigned base11 = (i+1 & N1-1)+N1*j+N1*N2*(k-1 & N3-1);
      unsigned base12 = i+N1*(j+1 & N2-1)+N1*N2*(k-1 & N3-1);
      float D_x, D_y, D_z, A_x, A_y, A_z, D, A;
      D_x = (0.25/dx1)*(
          (u_1[base2]+u_1[base])*(u_1[base2]+u_1[base]) -
          (u_1[base]+u_1[base1])*(u_1[base]+u_1[base1]));
      D_y = (0.25/dx2)*(
          (u_2[base4]+u_2[base5])*(u_1[base4]+u_1[base]) -
          (u_2[base]+u_2[base1])*(u_1[base]+u_1[base3]));
      D_z = (0.25/dx3)*(
          (u_3[base8]+u_3[base9])*(u_1[base8]+u_1[base]) -
          (u_3[base]+u_3[base1])*(u_1[base]+u_1[base7]));
      D = D_x + D_y + D_z;
      A_x =  (0.25/dx1)*(
          (u_1[base2]+u_1[base])*(u_1[base2]-u_1[base]) +
          (u_1[base]+u_1[base1])*(u_1[base]-u_1[base1]));
      A_y = (0.25/dx2)*(
            (u_2[base4]+u_2[base5])*(u_1[base4]-u_1[base]) +
            (u_2[base]+u_2[base1])*(u_1[base]-u_1[base3]));
      A_z = (0.25/dx3)*(
            (u_3[base8]+u_3[base9])*(u_1[base8]-u_1[base]) +
            (u_3[base]+u_3[base1])*(u_1[base]-u_1[base7]));
      A = A_x + A_y + A_z;
      S_1[base] = 0.5*(D+A);
      D_x = (0.25/dx1)*(
          (u_1[base2]+u_1[base6])*(u_2[base2]+u_2[base]) -
          (u_1[base]+u_1[base3])*(u_2[base]+u_2[base1]));
      D_y = (0.25/dx2)*(
          (u_2[base4]+u_2[base])*(u_2[base4]+u_2[base]) -
          (u_2[base]+u_2[base3])*(u_2[base]+u_2[base3]));
      D_z = (0.25/dx3)*(
          (u_3[base8]+u_3[base10])*(u_2[base8]+u_2[base]) -
          (u_3[base]+u_3[base3])*(u_2[base]+u_2[base7]));
      D = D_x + D_y + D_z;
      A_x =  (0.25/dx1)*(
          (u_1[base2]+u_1[base6])*(u_2[base2]-u_2[base]) +
          (u_1[base]+u_1[base3])*(u_2[base]-u_2[base1]));
      A_y = (0.25/dx2)*(
            (u_2[base4]+u_2[base])*(u_2[base4]-u_2[base]) +
            (u_2[base]+u_2[base3])*(u_2[base]-u_2[base3]));
      A_z = (0.25/dx3)*(
            (u_3[base8]+u_3[base10])*(u_2[base8]-u_2[base]) +
            (u_3[base]+u_3[base3])*(u_2[base]-u_2[base7]));
      A = A_x + A_y + A_z;
      S_2[base] = 0.5*(D+A);
      D_x = (0.25/dx1)*(
          (u_1[base2]+u_1[base11])*(u_3[base2]+u_3[base]) -
          (u_1[base]+u_1[base7])*(u_3[base]+u_3[base1]));
      D_y = (0.25/dx2)*(
          (u_2[base4]+u_2[base12])*(u_3[base4]+u_3[base]) -
          (u_2[base]+u_2[base7])*(u_3[base]+u_3[base3]));
      D_z = (0.25/dx3)*(
          (u_3[base8]+u_3[base])*(u_3[base8]+u_3[base]) -
          (u_3[base]+u_3[base7])*(u_3[base]+u_3[base7]));
      D = D_x + D_y + D_z;
      A_x =  (0.25/dx1)*(
          (u_1[base2]+u_1[base11])*(u_3[base2]-u_3[base]) +
          (u_1[base]+u_1[base7])*(u_3[base]-u_3[base1]));
      A_y = (0.25/dx2)*(
            (u_2[base4]+u_2[base12])*(u_3[base4]-u_3[base]) +
            (u_2[base]+u_2[base7])*(u_3[base]-u_3[base3]));
      A_z = (0.25/dx3)*(
            (u_3[base8]+u_3[base])*(u_3[base8]-u_3[base]) +
            (u_3[base]+u_3[base7])*(u_3[base]-u_3[base7]));
      A = A_x + A_y + A_z;
      S_3[base] = 0.5*(D+A);
    }
    """).build()

ib_prg = cl.Program(ctx, """
    #define MY_N1 (unsigned) 128 
    __kernel void spread_atomic(__global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, __global float *preamt_1, __global float *preamt_2, __global float *preamt_3)
    {
      unsigned k = get_global_id(0);
      //unsigned k = 16478;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      float s_1_stag = (X_1[k]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k];
      preamt_1[64*k+0] = c*my_F_1*ws01;
      preamt_1[64*k+1] = c*my_F_1*ws11;
      preamt_1[64*k+2] = c*my_F_1*ws21;
      preamt_1[64*k+3] = c*my_F_1*ws31;
      preamt_1[64*k+4] = c*my_F_1*ws41;
      preamt_1[64*k+5] = c*my_F_1*ws51;
      preamt_1[64*k+6] = c*my_F_1*ws61;
      preamt_1[64*k+7] = c*my_F_1*ws71;
      preamt_1[64*k+8] = c*my_F_1*ws81;
      preamt_1[64*k+9] = c*my_F_1*ws91;
      preamt_1[64*k+10] = c*my_F_1*wsa1;
      preamt_1[64*k+11] = c*my_F_1*wsb1;
      preamt_1[64*k+12] = c*my_F_1*wsc1;
      preamt_1[64*k+13] = c*my_F_1*wsd1;
      preamt_1[64*k+14] = c*my_F_1*wse1;
      preamt_1[64*k+15] = c*my_F_1*wsf1;

      preamt_1[64*k+16] = c*my_F_1*ws02;
      preamt_1[64*k+17] = c*my_F_1*ws12;
      preamt_1[64*k+18] = c*my_F_1*ws22;
      preamt_1[64*k+19] = c*my_F_1*ws32;
      preamt_1[64*k+20] = c*my_F_1*ws42;
      preamt_1[64*k+21] = c*my_F_1*ws52;
      preamt_1[64*k+22] = c*my_F_1*ws62;
      preamt_1[64*k+23] = c*my_F_1*ws72;
      preamt_1[64*k+24] = c*my_F_1*ws82;
      preamt_1[64*k+25] = c*my_F_1*ws92;
      preamt_1[64*k+26] = c*my_F_1*wsa2;
      preamt_1[64*k+27] = c*my_F_1*wsb2;
      preamt_1[64*k+28] = c*my_F_1*wsc2;
      preamt_1[64*k+29] = c*my_F_1*wsd2;
      preamt_1[64*k+30] = c*my_F_1*wse2;
      preamt_1[64*k+31] = c*my_F_1*wsf2;

      preamt_1[64*k+32] = c*my_F_1*ws03;
      preamt_1[64*k+33] = c*my_F_1*ws13;
      preamt_1[64*k+34] = c*my_F_1*ws23;
      preamt_1[64*k+35] = c*my_F_1*ws33;
      preamt_1[64*k+36] = c*my_F_1*ws43;
      preamt_1[64*k+37] = c*my_F_1*ws53;
      preamt_1[64*k+38] = c*my_F_1*ws63;
      preamt_1[64*k+39] = c*my_F_1*ws73;
      preamt_1[64*k+40] = c*my_F_1*ws83;
      preamt_1[64*k+41] = c*my_F_1*ws93;
      preamt_1[64*k+42] = c*my_F_1*wsa3;
      preamt_1[64*k+43] = c*my_F_1*wsb3;
      preamt_1[64*k+44] = c*my_F_1*wsc3;
      preamt_1[64*k+45] = c*my_F_1*wsd3;
      preamt_1[64*k+46] = c*my_F_1*wse3;
      preamt_1[64*k+47] = c*my_F_1*wsf3;

      preamt_1[64*k+48] = c*my_F_1*ws04;
      preamt_1[64*k+49] = c*my_F_1*ws14;
      preamt_1[64*k+50] = c*my_F_1*ws24;
      preamt_1[64*k+51] = c*my_F_1*ws34;
      preamt_1[64*k+52] = c*my_F_1*ws44;
      preamt_1[64*k+53] = c*my_F_1*ws54;
      preamt_1[64*k+54] = c*my_F_1*ws64;
      preamt_1[64*k+55] = c*my_F_1*ws74;
      preamt_1[64*k+56] = c*my_F_1*ws84;
      preamt_1[64*k+57] = c*my_F_1*ws94;
      preamt_1[64*k+58] = c*my_F_1*wsa4;
      preamt_1[64*k+59] = c*my_F_1*wsb4;
      preamt_1[64*k+60] = c*my_F_1*wsc4;
      preamt_1[64*k+61] = c*my_F_1*wsd4;
      preamt_1[64*k+62] = c*my_F_1*wse4;
      preamt_1[64*k+63] = c*my_F_1*wsf4;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_stag-1 & N2-1);
      ind_2y = (i_2_stag & N2-1);
      ind_2z = (i_2_stag+1 & N2-1);
      ind_2w = (i_2_stag+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k];
      preamt_2[64*k+0] = c*my_F_2*ws01;
      preamt_2[64*k+1] = c*my_F_2*ws11;
      preamt_2[64*k+2] = c*my_F_2*ws21;
      preamt_2[64*k+3] = c*my_F_2*ws31;
      preamt_2[64*k+4] = c*my_F_2*ws41;
      preamt_2[64*k+5] = c*my_F_2*ws51;
      preamt_2[64*k+6] = c*my_F_2*ws61;
      preamt_2[64*k+7] = c*my_F_2*ws71;
      preamt_2[64*k+8] = c*my_F_2*ws81;
      preamt_2[64*k+9] = c*my_F_2*ws91;
      preamt_2[64*k+10] = c*my_F_2*wsa1;
      preamt_2[64*k+11] = c*my_F_2*wsb1;
      preamt_2[64*k+12] = c*my_F_2*wsc1;
      preamt_2[64*k+13] = c*my_F_2*wsd1;
      preamt_2[64*k+14] = c*my_F_2*wse1;
      preamt_2[64*k+15] = c*my_F_2*wsf1;

      preamt_2[64*k+16] = c*my_F_2*ws02;
      preamt_2[64*k+17] = c*my_F_2*ws12;
      preamt_2[64*k+18] = c*my_F_2*ws22;
      preamt_2[64*k+19] = c*my_F_2*ws32;
      preamt_2[64*k+20] = c*my_F_2*ws42;
      preamt_2[64*k+21] = c*my_F_2*ws52;
      preamt_2[64*k+22] = c*my_F_2*ws62;
      preamt_2[64*k+23] = c*my_F_2*ws72;
      preamt_2[64*k+24] = c*my_F_2*ws82;
      preamt_2[64*k+25] = c*my_F_2*ws92;
      preamt_2[64*k+26] = c*my_F_2*wsa2;
      preamt_2[64*k+27] = c*my_F_2*wsb2;
      preamt_2[64*k+28] = c*my_F_2*wsc2;
      preamt_2[64*k+29] = c*my_F_2*wsd2;
      preamt_2[64*k+30] = c*my_F_2*wse2;
      preamt_2[64*k+31] = c*my_F_2*wsf2;

      preamt_2[64*k+32] = c*my_F_2*ws03;
      preamt_2[64*k+33] = c*my_F_2*ws13;
      preamt_2[64*k+34] = c*my_F_2*ws23;
      preamt_2[64*k+35] = c*my_F_2*ws33;
      preamt_2[64*k+36] = c*my_F_2*ws43;
      preamt_2[64*k+37] = c*my_F_2*ws53;
      preamt_2[64*k+38] = c*my_F_2*ws63;
      preamt_2[64*k+39] = c*my_F_2*ws73;
      preamt_2[64*k+40] = c*my_F_2*ws83;
      preamt_2[64*k+41] = c*my_F_2*ws93;
      preamt_2[64*k+42] = c*my_F_2*wsa3;
      preamt_2[64*k+43] = c*my_F_2*wsb3;
      preamt_2[64*k+44] = c*my_F_2*wsc3;
      preamt_2[64*k+45] = c*my_F_2*wsd3;
      preamt_2[64*k+46] = c*my_F_2*wse3;
      preamt_2[64*k+47] = c*my_F_2*wsf3;

      preamt_2[64*k+48] = c*my_F_2*ws04;
      preamt_2[64*k+49] = c*my_F_2*ws14;
      preamt_2[64*k+50] = c*my_F_2*ws24;
      preamt_2[64*k+51] = c*my_F_2*ws34;
      preamt_2[64*k+52] = c*my_F_2*ws44;
      preamt_2[64*k+53] = c*my_F_2*ws54;
      preamt_2[64*k+54] = c*my_F_2*ws64;
      preamt_2[64*k+55] = c*my_F_2*ws74;
      preamt_2[64*k+56] = c*my_F_2*ws84;
      preamt_2[64*k+57] = c*my_F_2*ws94;
      preamt_2[64*k+58] = c*my_F_2*wsa4;
      preamt_2[64*k+59] = c*my_F_2*wsb4;
      preamt_2[64*k+60] = c*my_F_2*wsc4;
      preamt_2[64*k+61] = c*my_F_2*wsd4;
      preamt_2[64*k+62] = c*my_F_2*wse4;
      preamt_2[64*k+63] = c*my_F_2*wsf4;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_stag-1 & N3-1);
      ind_3y = (i_3_stag & N3-1);
      ind_3z = (i_3_stag+1 & N3-1);
      ind_3w = (i_3_stag+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k];
      preamt_3[64*k+0] = c*my_F_3*ws01;
      preamt_3[64*k+1] = c*my_F_3*ws11;
      preamt_3[64*k+2] = c*my_F_3*ws21;
      preamt_3[64*k+3] = c*my_F_3*ws31;
      preamt_3[64*k+4] = c*my_F_3*ws41;
      preamt_3[64*k+5] = c*my_F_3*ws51;
      preamt_3[64*k+6] = c*my_F_3*ws61;
      preamt_3[64*k+7] = c*my_F_3*ws71;
      preamt_3[64*k+8] = c*my_F_3*ws81;
      preamt_3[64*k+9] = c*my_F_3*ws91;
      preamt_2[64*k+10] = c*my_F_3*wsa1;
      preamt_3[64*k+11] = c*my_F_3*wsb1;
      preamt_3[64*k+12] = c*my_F_3*wsc1;
      preamt_3[64*k+13] = c*my_F_3*wsd1;
      preamt_3[64*k+14] = c*my_F_3*wse1;
      preamt_3[64*k+15] = c*my_F_3*wsf1;

      preamt_3[64*k+16] = c*my_F_3*ws02;
      preamt_3[64*k+17] = c*my_F_3*ws12;
      preamt_3[64*k+18] = c*my_F_3*ws22;
      preamt_3[64*k+19] = c*my_F_3*ws32;
      preamt_3[64*k+20] = c*my_F_3*ws42;
      preamt_3[64*k+21] = c*my_F_3*ws52;
      preamt_3[64*k+22] = c*my_F_3*ws62;
      preamt_3[64*k+23] = c*my_F_3*ws72;
      preamt_3[64*k+24] = c*my_F_3*ws82;
      preamt_3[64*k+25] = c*my_F_3*ws92;
      preamt_3[64*k+26] = c*my_F_3*wsa2;
      preamt_3[64*k+27] = c*my_F_3*wsb2;
      preamt_3[64*k+28] = c*my_F_3*wsc2;
      preamt_3[64*k+29] = c*my_F_3*wsd2;
      preamt_3[64*k+30] = c*my_F_3*wse2;
      preamt_3[64*k+31] = c*my_F_3*wsf2;

      preamt_3[64*k+32] = c*my_F_3*ws03;
      preamt_3[64*k+33] = c*my_F_3*ws13;
      preamt_3[64*k+34] = c*my_F_3*ws23;
      preamt_3[64*k+35] = c*my_F_3*ws33;
      preamt_3[64*k+36] = c*my_F_3*ws43;
      preamt_3[64*k+37] = c*my_F_3*ws53;
      preamt_3[64*k+38] = c*my_F_3*ws63;
      preamt_3[64*k+39] = c*my_F_3*ws73;
      preamt_3[64*k+40] = c*my_F_3*ws83;
      preamt_3[64*k+41] = c*my_F_3*ws93;
      preamt_3[64*k+42] = c*my_F_3*wsa3;
      preamt_3[64*k+43] = c*my_F_3*wsb3;
      preamt_3[64*k+44] = c*my_F_3*wsc3;
      preamt_3[64*k+45] = c*my_F_3*wsd3;
      preamt_3[64*k+46] = c*my_F_3*wse3;
      preamt_3[64*k+47] = c*my_F_3*wsf3;

      preamt_3[64*k+48] = c*my_F_3*ws04;
      preamt_3[64*k+49] = c*my_F_3*ws14;
      preamt_3[64*k+50] = c*my_F_3*ws24;
      preamt_3[64*k+51] = c*my_F_3*ws34;
      preamt_3[64*k+52] = c*my_F_3*ws44;
      preamt_3[64*k+53] = c*my_F_3*ws54;
      preamt_3[64*k+54] = c*my_F_3*ws64;
      preamt_3[64*k+55] = c*my_F_3*ws74;
      preamt_3[64*k+56] = c*my_F_3*ws84;
      preamt_3[64*k+57] = c*my_F_3*ws94;
      preamt_3[64*k+58] = c*my_F_3*wsa4;
      preamt_3[64*k+59] = c*my_F_3*wsb4;
      preamt_3[64*k+60] = c*my_F_3*wsc4;
      preamt_3[64*k+61] = c*my_F_3*wsd4;
      preamt_3[64*k+62] = c*my_F_3*wse4;
      preamt_3[64*k+63] = c*my_F_3*wsf4;
    }
    __kernel void spread_pre(__global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, __global unsigned *preind_1, __global unsigned *preind_2, __global unsigned *preind_3, __global float *preamt_1, __global float *preamt_2, __global float *preamt_3)
    {
      unsigned k = get_global_id(0);
      //unsigned k = 16478;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      float c = dtheta/(dx1*dx2*dx3);

      unsigned ind_1x, ind_1y, ind_1z, ind_1w;
      unsigned ind_2x, ind_2y, ind_2z, ind_2w;
      unsigned ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      float s_1_stag = (X_1[k]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k];
      preamt_1[64*k+0] = c*my_F_1*ws01;
      preamt_1[64*k+1] = c*my_F_1*ws11;
      preamt_1[64*k+2] = c*my_F_1*ws21;
      preamt_1[64*k+3] = c*my_F_1*ws31;
      preamt_1[64*k+4] = c*my_F_1*ws41;
      preamt_1[64*k+5] = c*my_F_1*ws51;
      preamt_1[64*k+6] = c*my_F_1*ws61;
      preamt_1[64*k+7] = c*my_F_1*ws71;
      preamt_1[64*k+8] = c*my_F_1*ws81;
      preamt_1[64*k+9] = c*my_F_1*ws91;
      preamt_1[64*k+10] = c*my_F_1*wsa1;
      preamt_1[64*k+11] = c*my_F_1*wsb1;
      preamt_1[64*k+12] = c*my_F_1*wsc1;
      preamt_1[64*k+13] = c*my_F_1*wsd1;
      preamt_1[64*k+14] = c*my_F_1*wse1;
      preamt_1[64*k+15] = c*my_F_1*wsf1;

      preamt_1[64*k+16] = c*my_F_1*ws02;
      preamt_1[64*k+17] = c*my_F_1*ws12;
      preamt_1[64*k+18] = c*my_F_1*ws22;
      preamt_1[64*k+19] = c*my_F_1*ws32;
      preamt_1[64*k+20] = c*my_F_1*ws42;
      preamt_1[64*k+21] = c*my_F_1*ws52;
      preamt_1[64*k+22] = c*my_F_1*ws62;
      preamt_1[64*k+23] = c*my_F_1*ws72;
      preamt_1[64*k+24] = c*my_F_1*ws82;
      preamt_1[64*k+25] = c*my_F_1*ws92;
      preamt_1[64*k+26] = c*my_F_1*wsa2;
      preamt_1[64*k+27] = c*my_F_1*wsb2;
      preamt_1[64*k+28] = c*my_F_1*wsc2;
      preamt_1[64*k+29] = c*my_F_1*wsd2;
      preamt_1[64*k+30] = c*my_F_1*wse2;
      preamt_1[64*k+31] = c*my_F_1*wsf2;

      preamt_1[64*k+32] = c*my_F_1*ws03;
      preamt_1[64*k+33] = c*my_F_1*ws13;
      preamt_1[64*k+34] = c*my_F_1*ws23;
      preamt_1[64*k+35] = c*my_F_1*ws33;
      preamt_1[64*k+36] = c*my_F_1*ws43;
      preamt_1[64*k+37] = c*my_F_1*ws53;
      preamt_1[64*k+38] = c*my_F_1*ws63;
      preamt_1[64*k+39] = c*my_F_1*ws73;
      preamt_1[64*k+40] = c*my_F_1*ws83;
      preamt_1[64*k+41] = c*my_F_1*ws93;
      preamt_1[64*k+42] = c*my_F_1*wsa3;
      preamt_1[64*k+43] = c*my_F_1*wsb3;
      preamt_1[64*k+44] = c*my_F_1*wsc3;
      preamt_1[64*k+45] = c*my_F_1*wsd3;
      preamt_1[64*k+46] = c*my_F_1*wse3;
      preamt_1[64*k+47] = c*my_F_1*wsf3;

      preamt_1[64*k+48] = c*my_F_1*ws04;
      preamt_1[64*k+49] = c*my_F_1*ws14;
      preamt_1[64*k+50] = c*my_F_1*ws24;
      preamt_1[64*k+51] = c*my_F_1*ws34;
      preamt_1[64*k+52] = c*my_F_1*ws44;
      preamt_1[64*k+53] = c*my_F_1*ws54;
      preamt_1[64*k+54] = c*my_F_1*ws64;
      preamt_1[64*k+55] = c*my_F_1*ws74;
      preamt_1[64*k+56] = c*my_F_1*ws84;
      preamt_1[64*k+57] = c*my_F_1*ws94;
      preamt_1[64*k+58] = c*my_F_1*wsa4;
      preamt_1[64*k+59] = c*my_F_1*wsb4;
      preamt_1[64*k+60] = c*my_F_1*wsc4;
      preamt_1[64*k+61] = c*my_F_1*wsd4;
      preamt_1[64*k+62] = c*my_F_1*wse4;
      preamt_1[64*k+63] = c*my_F_1*wsf4;

      preind_1[64*k+0] = ind_1x+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+1] = ind_1y+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+2] = ind_1z+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+3] = ind_1w+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+4] = ind_1x+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+5] = ind_1y+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+6] = ind_1z+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+7] = ind_1w+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+8] = ind_1x+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+9] = ind_1y+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+10] = ind_1z+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+11] = ind_1w+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+12] = ind_1x+N1*ind_2w+N1*N2*ind_3x; 
      preind_1[64*k+13] = ind_1y+N1*ind_2w+N1*N2*ind_3x; 
      preind_1[64*k+14] = ind_1z+N1*ind_2w+N1*N2*ind_3x; 
      preind_1[64*k+15] = ind_1w+N1*ind_2w+N1*N2*ind_3x; 

      preind_1[64*k+16] = ind_1x+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+17] = ind_1y+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+18] = ind_1z+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+19] = ind_1w+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+20] = ind_1x+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+21] = ind_1y+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+22] = ind_1z+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+23] = ind_1w+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+24] = ind_1x+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+25] = ind_1y+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+26] = ind_1z+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+27] = ind_1w+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+28] = ind_1x+N1*ind_2w+N1*N2*ind_3y; 
      preind_1[64*k+29] = ind_1y+N1*ind_2w+N1*N2*ind_3y; 
      preind_1[64*k+30] = ind_1z+N1*ind_2w+N1*N2*ind_3y; 
      preind_1[64*k+31] = ind_1w+N1*ind_2w+N1*N2*ind_3y; 

      preind_1[64*k+32] = ind_1x+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+33] = ind_1y+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+34] = ind_1z+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+35] = ind_1w+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+36] = ind_1x+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+37] = ind_1y+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+38] = ind_1z+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+39] = ind_1w+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+40] = ind_1x+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+41] = ind_1y+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+42] = ind_1z+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+43] = ind_1w+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+44] = ind_1x+N1*ind_2w+N1*N2*ind_3z; 
      preind_1[64*k+45] = ind_1y+N1*ind_2w+N1*N2*ind_3z; 
      preind_1[64*k+46] = ind_1z+N1*ind_2w+N1*N2*ind_3z; 
      preind_1[64*k+47] = ind_1w+N1*ind_2w+N1*N2*ind_3z; 

      preind_1[64*k+48] = ind_1x+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+49] = ind_1y+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+50] = ind_1z+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+51] = ind_1w+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+52] = ind_1x+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+53] = ind_1y+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+54] = ind_1z+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+55] = ind_1w+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+56] = ind_1x+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+57] = ind_1y+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+58] = ind_1z+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+59] = ind_1w+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+60] = ind_1x+N1*ind_2w+N1*N2*ind_3w; 
      preind_1[64*k+61] = ind_1y+N1*ind_2w+N1*N2*ind_3w; 
      preind_1[64*k+62] = ind_1z+N1*ind_2w+N1*N2*ind_3w; 
      preind_1[64*k+63] = ind_1w+N1*ind_2w+N1*N2*ind_3w; 

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_stag-1 & N2-1);
      ind_2y = (i_2_stag & N2-1);
      ind_2z = (i_2_stag+1 & N2-1);
      ind_2w = (i_2_stag+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k];
      preamt_2[64*k+0] = c*my_F_2*ws01;
      preamt_2[64*k+1] = c*my_F_2*ws11;
      preamt_2[64*k+2] = c*my_F_2*ws21;
      preamt_2[64*k+3] = c*my_F_2*ws31;
      preamt_2[64*k+4] = c*my_F_2*ws41;
      preamt_2[64*k+5] = c*my_F_2*ws51;
      preamt_2[64*k+6] = c*my_F_2*ws61;
      preamt_2[64*k+7] = c*my_F_2*ws71;
      preamt_2[64*k+8] = c*my_F_2*ws81;
      preamt_2[64*k+9] = c*my_F_2*ws91;
      preamt_2[64*k+10] = c*my_F_2*wsa1;
      preamt_2[64*k+11] = c*my_F_2*wsb1;
      preamt_2[64*k+12] = c*my_F_2*wsc1;
      preamt_2[64*k+13] = c*my_F_2*wsd1;
      preamt_2[64*k+14] = c*my_F_2*wse1;
      preamt_2[64*k+15] = c*my_F_2*wsf1;

      preamt_2[64*k+16] = c*my_F_2*ws02;
      preamt_2[64*k+17] = c*my_F_2*ws12;
      preamt_2[64*k+18] = c*my_F_2*ws22;
      preamt_2[64*k+19] = c*my_F_2*ws32;
      preamt_2[64*k+20] = c*my_F_2*ws42;
      preamt_2[64*k+21] = c*my_F_2*ws52;
      preamt_2[64*k+22] = c*my_F_2*ws62;
      preamt_2[64*k+23] = c*my_F_2*ws72;
      preamt_2[64*k+24] = c*my_F_2*ws82;
      preamt_2[64*k+25] = c*my_F_2*ws92;
      preamt_2[64*k+26] = c*my_F_2*wsa2;
      preamt_2[64*k+27] = c*my_F_2*wsb2;
      preamt_2[64*k+28] = c*my_F_2*wsc2;
      preamt_2[64*k+29] = c*my_F_2*wsd2;
      preamt_2[64*k+30] = c*my_F_2*wse2;
      preamt_2[64*k+31] = c*my_F_2*wsf2;

      preamt_2[64*k+32] = c*my_F_2*ws03;
      preamt_2[64*k+33] = c*my_F_2*ws13;
      preamt_2[64*k+34] = c*my_F_2*ws23;
      preamt_2[64*k+35] = c*my_F_2*ws33;
      preamt_2[64*k+36] = c*my_F_2*ws43;
      preamt_2[64*k+37] = c*my_F_2*ws53;
      preamt_2[64*k+38] = c*my_F_2*ws63;
      preamt_2[64*k+39] = c*my_F_2*ws73;
      preamt_2[64*k+40] = c*my_F_2*ws83;
      preamt_2[64*k+41] = c*my_F_2*ws93;
      preamt_2[64*k+42] = c*my_F_2*wsa3;
      preamt_2[64*k+43] = c*my_F_2*wsb3;
      preamt_2[64*k+44] = c*my_F_2*wsc3;
      preamt_2[64*k+45] = c*my_F_2*wsd3;
      preamt_2[64*k+46] = c*my_F_2*wse3;
      preamt_2[64*k+47] = c*my_F_2*wsf3;

      preamt_2[64*k+48] = c*my_F_2*ws04;
      preamt_2[64*k+49] = c*my_F_2*ws14;
      preamt_2[64*k+50] = c*my_F_2*ws24;
      preamt_2[64*k+51] = c*my_F_2*ws34;
      preamt_2[64*k+52] = c*my_F_2*ws44;
      preamt_2[64*k+53] = c*my_F_2*ws54;
      preamt_2[64*k+54] = c*my_F_2*ws64;
      preamt_2[64*k+55] = c*my_F_2*ws74;
      preamt_2[64*k+56] = c*my_F_2*ws84;
      preamt_2[64*k+57] = c*my_F_2*ws94;
      preamt_2[64*k+58] = c*my_F_2*wsa4;
      preamt_2[64*k+59] = c*my_F_2*wsb4;
      preamt_2[64*k+60] = c*my_F_2*wsc4;
      preamt_2[64*k+61] = c*my_F_2*wsd4;
      preamt_2[64*k+62] = c*my_F_2*wse4;
      preamt_2[64*k+63] = c*my_F_2*wsf4;

      preind_2[64*k+0] = ind_1x+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+1] = ind_1y+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+2] = ind_1z+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+3] = ind_1w+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+4] = ind_1x+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+5] = ind_1y+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+6] = ind_1z+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+7] = ind_1w+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+8] = ind_1x+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+9] = ind_1y+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+10] = ind_1z+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+11] = ind_1w+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+12] = ind_1x+N1*ind_2w+N1*N2*ind_3x; 
      preind_2[64*k+13] = ind_1y+N1*ind_2w+N1*N2*ind_3x; 
      preind_2[64*k+14] = ind_1z+N1*ind_2w+N1*N2*ind_3x; 
      preind_2[64*k+15] = ind_1w+N1*ind_2w+N1*N2*ind_3x; 

      preind_2[64*k+16] = ind_1x+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+17] = ind_1y+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+18] = ind_1z+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+19] = ind_1w+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+20] = ind_1x+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+21] = ind_1y+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+22] = ind_1z+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+23] = ind_1w+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+24] = ind_1x+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+25] = ind_1y+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+26] = ind_1z+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+27] = ind_1w+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+28] = ind_1x+N1*ind_2w+N1*N2*ind_3y; 
      preind_2[64*k+29] = ind_1y+N1*ind_2w+N1*N2*ind_3y; 
      preind_2[64*k+30] = ind_1z+N1*ind_2w+N1*N2*ind_3y; 
      preind_2[64*k+31] = ind_1w+N1*ind_2w+N1*N2*ind_3y; 

      preind_2[64*k+32] = ind_1x+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+33] = ind_1y+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+34] = ind_1z+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+35] = ind_1w+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+36] = ind_1x+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+37] = ind_1y+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+38] = ind_1z+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+39] = ind_1w+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+40] = ind_1x+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+41] = ind_1y+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+42] = ind_1z+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+43] = ind_1w+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+44] = ind_1x+N1*ind_2w+N1*N2*ind_3z; 
      preind_2[64*k+45] = ind_1y+N1*ind_2w+N1*N2*ind_3z; 
      preind_2[64*k+46] = ind_1z+N1*ind_2w+N1*N2*ind_3z; 
      preind_2[64*k+47] = ind_1w+N1*ind_2w+N1*N2*ind_3z; 

      preind_2[64*k+48] = ind_1x+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+49] = ind_1y+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+50] = ind_1z+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+51] = ind_1w+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+52] = ind_1x+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+53] = ind_1y+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+54] = ind_1z+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+55] = ind_1w+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+56] = ind_1x+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+57] = ind_1y+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+58] = ind_1z+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+59] = ind_1w+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+60] = ind_1x+N1*ind_2w+N1*N2*ind_3w; 
      preind_2[64*k+61] = ind_1y+N1*ind_2w+N1*N2*ind_3w; 
      preind_2[64*k+62] = ind_1z+N1*ind_2w+N1*N2*ind_3w; 
      preind_2[64*k+63] = ind_1w+N1*ind_2w+N1*N2*ind_3w; 

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_stag-1 & N3-1);
      ind_3y = (i_3_stag & N3-1);
      ind_3z = (i_3_stag+1 & N3-1);
      ind_3w = (i_3_stag+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k];
      preamt_3[64*k+0] = c*my_F_3*ws01;
      preamt_3[64*k+1] = c*my_F_3*ws11;
      preamt_3[64*k+2] = c*my_F_3*ws21;
      preamt_3[64*k+3] = c*my_F_3*ws31;
      preamt_3[64*k+4] = c*my_F_3*ws41;
      preamt_3[64*k+5] = c*my_F_3*ws51;
      preamt_3[64*k+6] = c*my_F_3*ws61;
      preamt_3[64*k+7] = c*my_F_3*ws71;
      preamt_3[64*k+8] = c*my_F_3*ws81;
      preamt_3[64*k+9] = c*my_F_3*ws91;
      preamt_3[64*k+10] = c*my_F_3*wsa1;
      preamt_3[64*k+11] = c*my_F_3*wsb1;
      preamt_3[64*k+12] = c*my_F_3*wsc1;
      preamt_3[64*k+13] = c*my_F_3*wsd1;
      preamt_3[64*k+14] = c*my_F_3*wse1;
      preamt_3[64*k+15] = c*my_F_3*wsf1;

      preamt_3[64*k+16] = c*my_F_3*ws02;
      preamt_3[64*k+17] = c*my_F_3*ws12;
      preamt_3[64*k+18] = c*my_F_3*ws22;
      preamt_3[64*k+19] = c*my_F_3*ws32;
      preamt_3[64*k+20] = c*my_F_3*ws42;
      preamt_3[64*k+21] = c*my_F_3*ws52;
      preamt_3[64*k+22] = c*my_F_3*ws62;
      preamt_3[64*k+23] = c*my_F_3*ws72;
      preamt_3[64*k+24] = c*my_F_3*ws82;
      preamt_3[64*k+25] = c*my_F_3*ws92;
      preamt_3[64*k+26] = c*my_F_3*wsa2;
      preamt_3[64*k+27] = c*my_F_3*wsb2;
      preamt_3[64*k+28] = c*my_F_3*wsc2;
      preamt_3[64*k+29] = c*my_F_3*wsd2;
      preamt_3[64*k+30] = c*my_F_3*wse2;
      preamt_3[64*k+31] = c*my_F_3*wsf2;

      preamt_3[64*k+32] = c*my_F_3*ws03;
      preamt_3[64*k+33] = c*my_F_3*ws13;
      preamt_3[64*k+34] = c*my_F_3*ws23;
      preamt_3[64*k+35] = c*my_F_3*ws33;
      preamt_3[64*k+36] = c*my_F_3*ws43;
      preamt_3[64*k+37] = c*my_F_3*ws53;
      preamt_3[64*k+38] = c*my_F_3*ws63;
      preamt_3[64*k+39] = c*my_F_3*ws73;
      preamt_3[64*k+40] = c*my_F_3*ws83;
      preamt_3[64*k+41] = c*my_F_3*ws93;
      preamt_3[64*k+42] = c*my_F_3*wsa3;
      preamt_3[64*k+43] = c*my_F_3*wsb3;
      preamt_3[64*k+44] = c*my_F_3*wsc3;
      preamt_3[64*k+45] = c*my_F_3*wsd3;
      preamt_3[64*k+46] = c*my_F_3*wse3;
      preamt_3[64*k+47] = c*my_F_3*wsf3;

      preamt_3[64*k+48] = c*my_F_3*ws04;
      preamt_3[64*k+49] = c*my_F_3*ws14;
      preamt_3[64*k+50] = c*my_F_3*ws24;
      preamt_3[64*k+51] = c*my_F_3*ws34;
      preamt_3[64*k+52] = c*my_F_3*ws44;
      preamt_3[64*k+53] = c*my_F_3*ws54;
      preamt_3[64*k+54] = c*my_F_3*ws64;
      preamt_3[64*k+55] = c*my_F_3*ws74;
      preamt_3[64*k+56] = c*my_F_3*ws84;
      preamt_3[64*k+57] = c*my_F_3*ws94;
      preamt_3[64*k+58] = c*my_F_3*wsa4;
      preamt_3[64*k+59] = c*my_F_3*wsb4;
      preamt_3[64*k+60] = c*my_F_3*wsc4;
      preamt_3[64*k+61] = c*my_F_3*wsd4;
      preamt_3[64*k+62] = c*my_F_3*wse4;
      preamt_3[64*k+63] = c*my_F_3*wsf4;

      preind_3[64*k+0] = ind_1x+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+1] = ind_1y+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+2] = ind_1z+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+3] = ind_1w+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+4] = ind_1x+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+5] = ind_1y+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+6] = ind_1z+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+7] = ind_1w+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+8] = ind_1x+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+9] = ind_1y+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+10] = ind_1z+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+11] = ind_1w+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+12] = ind_1x+N1*ind_2w+N1*N2*ind_3x; 
      preind_3[64*k+13] = ind_1y+N1*ind_2w+N1*N2*ind_3x; 
      preind_3[64*k+14] = ind_1z+N1*ind_2w+N1*N2*ind_3x; 
      preind_3[64*k+15] = ind_1w+N1*ind_2w+N1*N2*ind_3x; 

      preind_3[64*k+16] = ind_1x+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+17] = ind_1y+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+18] = ind_1z+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+19] = ind_1w+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+20] = ind_1x+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+21] = ind_1y+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+22] = ind_1z+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+23] = ind_1w+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+24] = ind_1x+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+25] = ind_1y+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+26] = ind_1z+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+27] = ind_1w+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+28] = ind_1x+N1*ind_2w+N1*N2*ind_3y; 
      preind_3[64*k+29] = ind_1y+N1*ind_2w+N1*N2*ind_3y; 
      preind_3[64*k+30] = ind_1z+N1*ind_2w+N1*N2*ind_3y; 
      preind_3[64*k+31] = ind_1w+N1*ind_2w+N1*N2*ind_3y; 

      preind_3[64*k+32] = ind_1x+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+33] = ind_1y+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+34] = ind_1z+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+35] = ind_1w+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+36] = ind_1x+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+37] = ind_1y+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+38] = ind_1z+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+39] = ind_1w+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+40] = ind_1x+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+41] = ind_1y+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+42] = ind_1z+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+43] = ind_1w+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+44] = ind_1x+N1*ind_2w+N1*N2*ind_3z; 
      preind_3[64*k+45] = ind_1y+N1*ind_2w+N1*N2*ind_3z; 
      preind_3[64*k+46] = ind_1z+N1*ind_2w+N1*N2*ind_3z; 
      preind_3[64*k+47] = ind_1w+N1*ind_2w+N1*N2*ind_3z; 

      preind_3[64*k+48] = ind_1x+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+49] = ind_1y+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+50] = ind_1z+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+51] = ind_1w+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+52] = ind_1x+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+53] = ind_1y+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+54] = ind_1z+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+55] = ind_1w+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+56] = ind_1x+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+57] = ind_1y+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+58] = ind_1z+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+59] = ind_1w+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+60] = ind_1x+N1*ind_2w+N1*N2*ind_3w; 
      preind_3[64*k+61] = ind_1y+N1*ind_2w+N1*N2*ind_3w; 
      preind_3[64*k+62] = ind_1z+N1*ind_2w+N1*N2*ind_3w; 
      preind_3[64*k+63] = ind_1w+N1*ind_2w+N1*N2*ind_3w; 
    }
    __kernel void spread_pre_serial(__global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned k, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, __global unsigned *preind_1, __global unsigned *preind_2, __global unsigned *preind_3, __global float *preamt_1, __global float *preamt_2, __global float *preamt_3)
    {
      //unsigned k = get_global_id(0);
      //unsigned k = 16478;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      float c = dtheta/(dx1*dx2*dx3);

      unsigned ind_1x, ind_1y, ind_1z, ind_1w;
      unsigned ind_2x, ind_2y, ind_2z, ind_2w;
      unsigned ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      float s_1_stag = (X_1[k]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k];
      preamt_1[64*k+0] = c*my_F_1*ws01;
      preamt_1[64*k+1] = c*my_F_1*ws11;
      preamt_1[64*k+2] = c*my_F_1*ws21;
      preamt_1[64*k+3] = c*my_F_1*ws31;
      preamt_1[64*k+4] = c*my_F_1*ws41;
      preamt_1[64*k+5] = c*my_F_1*ws51;
      preamt_1[64*k+6] = c*my_F_1*ws61;
      preamt_1[64*k+7] = c*my_F_1*ws71;
      preamt_1[64*k+8] = c*my_F_1*ws81;
      preamt_1[64*k+9] = c*my_F_1*ws91;
      preamt_1[64*k+10] = c*my_F_1*wsa1;
      preamt_1[64*k+11] = c*my_F_1*wsb1;
      preamt_1[64*k+12] = c*my_F_1*wsc1;
      preamt_1[64*k+13] = c*my_F_1*wsd1;
      preamt_1[64*k+14] = c*my_F_1*wse1;
      preamt_1[64*k+15] = c*my_F_1*wsf1;

      preamt_1[64*k+16] = c*my_F_1*ws02;
      preamt_1[64*k+17] = c*my_F_1*ws12;
      preamt_1[64*k+18] = c*my_F_1*ws22;
      preamt_1[64*k+19] = c*my_F_1*ws32;
      preamt_1[64*k+20] = c*my_F_1*ws42;
      preamt_1[64*k+21] = c*my_F_1*ws52;
      preamt_1[64*k+22] = c*my_F_1*ws62;
      preamt_1[64*k+23] = c*my_F_1*ws72;
      preamt_1[64*k+24] = c*my_F_1*ws82;
      preamt_1[64*k+25] = c*my_F_1*ws92;
      preamt_1[64*k+26] = c*my_F_1*wsa2;
      preamt_1[64*k+27] = c*my_F_1*wsb2;
      preamt_1[64*k+28] = c*my_F_1*wsc2;
      preamt_1[64*k+29] = c*my_F_1*wsd2;
      preamt_1[64*k+30] = c*my_F_1*wse2;
      preamt_1[64*k+31] = c*my_F_1*wsf2;

      preamt_1[64*k+32] = c*my_F_1*ws03;
      preamt_1[64*k+33] = c*my_F_1*ws13;
      preamt_1[64*k+34] = c*my_F_1*ws23;
      preamt_1[64*k+35] = c*my_F_1*ws33;
      preamt_1[64*k+36] = c*my_F_1*ws43;
      preamt_1[64*k+37] = c*my_F_1*ws53;
      preamt_1[64*k+38] = c*my_F_1*ws63;
      preamt_1[64*k+39] = c*my_F_1*ws73;
      preamt_1[64*k+40] = c*my_F_1*ws83;
      preamt_1[64*k+41] = c*my_F_1*ws93;
      preamt_1[64*k+42] = c*my_F_1*wsa3;
      preamt_1[64*k+43] = c*my_F_1*wsb3;
      preamt_1[64*k+44] = c*my_F_1*wsc3;
      preamt_1[64*k+45] = c*my_F_1*wsd3;
      preamt_1[64*k+46] = c*my_F_1*wse3;
      preamt_1[64*k+47] = c*my_F_1*wsf3;

      preamt_1[64*k+48] = c*my_F_1*ws04;
      preamt_1[64*k+49] = c*my_F_1*ws14;
      preamt_1[64*k+50] = c*my_F_1*ws24;
      preamt_1[64*k+51] = c*my_F_1*ws34;
      preamt_1[64*k+52] = c*my_F_1*ws44;
      preamt_1[64*k+53] = c*my_F_1*ws54;
      preamt_1[64*k+54] = c*my_F_1*ws64;
      preamt_1[64*k+55] = c*my_F_1*ws74;
      preamt_1[64*k+56] = c*my_F_1*ws84;
      preamt_1[64*k+57] = c*my_F_1*ws94;
      preamt_1[64*k+58] = c*my_F_1*wsa4;
      preamt_1[64*k+59] = c*my_F_1*wsb4;
      preamt_1[64*k+60] = c*my_F_1*wsc4;
      preamt_1[64*k+61] = c*my_F_1*wsd4;
      preamt_1[64*k+62] = c*my_F_1*wse4;
      preamt_1[64*k+63] = c*my_F_1*wsf4;

      preind_1[64*k+0] = ind_1x+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+1] = ind_1y+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+2] = ind_1z+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+3] = ind_1w+N1*ind_2x+N1*N2*ind_3x; 
      preind_1[64*k+4] = ind_1x+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+5] = ind_1y+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+6] = ind_1z+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+7] = ind_1w+N1*ind_2y+N1*N2*ind_3x; 
      preind_1[64*k+8] = ind_1x+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+9] = ind_1y+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+10] = ind_1z+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+11] = ind_1w+N1*ind_2z+N1*N2*ind_3x; 
      preind_1[64*k+12] = ind_1x+N1*ind_2w+N1*N2*ind_3x; 
      preind_1[64*k+13] = ind_1y+N1*ind_2w+N1*N2*ind_3x; 
      preind_1[64*k+14] = ind_1z+N1*ind_2w+N1*N2*ind_3x; 
      preind_1[64*k+15] = ind_1w+N1*ind_2w+N1*N2*ind_3x; 

      preind_1[64*k+16] = ind_1x+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+17] = ind_1y+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+18] = ind_1z+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+19] = ind_1w+N1*ind_2x+N1*N2*ind_3y; 
      preind_1[64*k+20] = ind_1x+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+21] = ind_1y+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+22] = ind_1z+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+23] = ind_1w+N1*ind_2y+N1*N2*ind_3y; 
      preind_1[64*k+24] = ind_1x+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+25] = ind_1y+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+26] = ind_1z+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+27] = ind_1w+N1*ind_2z+N1*N2*ind_3y; 
      preind_1[64*k+28] = ind_1x+N1*ind_2w+N1*N2*ind_3y; 
      preind_1[64*k+29] = ind_1y+N1*ind_2w+N1*N2*ind_3y; 
      preind_1[64*k+30] = ind_1z+N1*ind_2w+N1*N2*ind_3y; 
      preind_1[64*k+31] = ind_1w+N1*ind_2w+N1*N2*ind_3y; 

      preind_1[64*k+32] = ind_1x+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+33] = ind_1y+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+34] = ind_1z+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+35] = ind_1w+N1*ind_2x+N1*N2*ind_3z; 
      preind_1[64*k+36] = ind_1x+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+37] = ind_1y+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+38] = ind_1z+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+39] = ind_1w+N1*ind_2y+N1*N2*ind_3z; 
      preind_1[64*k+40] = ind_1x+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+41] = ind_1y+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+42] = ind_1z+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+43] = ind_1w+N1*ind_2z+N1*N2*ind_3z; 
      preind_1[64*k+44] = ind_1x+N1*ind_2w+N1*N2*ind_3z; 
      preind_1[64*k+45] = ind_1y+N1*ind_2w+N1*N2*ind_3z; 
      preind_1[64*k+46] = ind_1z+N1*ind_2w+N1*N2*ind_3z; 
      preind_1[64*k+47] = ind_1w+N1*ind_2w+N1*N2*ind_3z; 

      preind_1[64*k+48] = ind_1x+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+49] = ind_1y+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+50] = ind_1z+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+51] = ind_1w+N1*ind_2x+N1*N2*ind_3w; 
      preind_1[64*k+52] = ind_1x+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+53] = ind_1y+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+54] = ind_1z+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+55] = ind_1w+N1*ind_2y+N1*N2*ind_3w; 
      preind_1[64*k+56] = ind_1x+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+57] = ind_1y+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+58] = ind_1z+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+59] = ind_1w+N1*ind_2z+N1*N2*ind_3w; 
      preind_1[64*k+60] = ind_1x+N1*ind_2w+N1*N2*ind_3w; 
      preind_1[64*k+61] = ind_1y+N1*ind_2w+N1*N2*ind_3w; 
      preind_1[64*k+62] = ind_1z+N1*ind_2w+N1*N2*ind_3w; 
      preind_1[64*k+63] = ind_1w+N1*ind_2w+N1*N2*ind_3w; 

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_stag-1 & N2-1);
      ind_2y = (i_2_stag & N2-1);
      ind_2z = (i_2_stag+1 & N2-1);
      ind_2w = (i_2_stag+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k];
      preamt_2[64*k+0] = c*my_F_2*ws01;
      preamt_2[64*k+1] = c*my_F_2*ws11;
      preamt_2[64*k+2] = c*my_F_2*ws21;
      preamt_2[64*k+3] = c*my_F_2*ws31;
      preamt_2[64*k+4] = c*my_F_2*ws41;
      preamt_2[64*k+5] = c*my_F_2*ws51;
      preamt_2[64*k+6] = c*my_F_2*ws61;
      preamt_2[64*k+7] = c*my_F_2*ws71;
      preamt_2[64*k+8] = c*my_F_2*ws81;
      preamt_2[64*k+9] = c*my_F_2*ws91;
      preamt_2[64*k+10] = c*my_F_2*wsa1;
      preamt_2[64*k+11] = c*my_F_2*wsb1;
      preamt_2[64*k+12] = c*my_F_2*wsc1;
      preamt_2[64*k+13] = c*my_F_2*wsd1;
      preamt_2[64*k+14] = c*my_F_2*wse1;
      preamt_2[64*k+15] = c*my_F_2*wsf1;

      preamt_2[64*k+16] = c*my_F_2*ws02;
      preamt_2[64*k+17] = c*my_F_2*ws12;
      preamt_2[64*k+18] = c*my_F_2*ws22;
      preamt_2[64*k+19] = c*my_F_2*ws32;
      preamt_2[64*k+20] = c*my_F_2*ws42;
      preamt_2[64*k+21] = c*my_F_2*ws52;
      preamt_2[64*k+22] = c*my_F_2*ws62;
      preamt_2[64*k+23] = c*my_F_2*ws72;
      preamt_2[64*k+24] = c*my_F_2*ws82;
      preamt_2[64*k+25] = c*my_F_2*ws92;
      preamt_2[64*k+26] = c*my_F_2*wsa2;
      preamt_2[64*k+27] = c*my_F_2*wsb2;
      preamt_2[64*k+28] = c*my_F_2*wsc2;
      preamt_2[64*k+29] = c*my_F_2*wsd2;
      preamt_2[64*k+30] = c*my_F_2*wse2;
      preamt_2[64*k+31] = c*my_F_2*wsf2;

      preamt_2[64*k+32] = c*my_F_2*ws03;
      preamt_2[64*k+33] = c*my_F_2*ws13;
      preamt_2[64*k+34] = c*my_F_2*ws23;
      preamt_2[64*k+35] = c*my_F_2*ws33;
      preamt_2[64*k+36] = c*my_F_2*ws43;
      preamt_2[64*k+37] = c*my_F_2*ws53;
      preamt_2[64*k+38] = c*my_F_2*ws63;
      preamt_2[64*k+39] = c*my_F_2*ws73;
      preamt_2[64*k+40] = c*my_F_2*ws83;
      preamt_2[64*k+41] = c*my_F_2*ws93;
      preamt_2[64*k+42] = c*my_F_2*wsa3;
      preamt_2[64*k+43] = c*my_F_2*wsb3;
      preamt_2[64*k+44] = c*my_F_2*wsc3;
      preamt_2[64*k+45] = c*my_F_2*wsd3;
      preamt_2[64*k+46] = c*my_F_2*wse3;
      preamt_2[64*k+47] = c*my_F_2*wsf3;

      preamt_2[64*k+48] = c*my_F_2*ws04;
      preamt_2[64*k+49] = c*my_F_2*ws14;
      preamt_2[64*k+50] = c*my_F_2*ws24;
      preamt_2[64*k+51] = c*my_F_2*ws34;
      preamt_2[64*k+52] = c*my_F_2*ws44;
      preamt_2[64*k+53] = c*my_F_2*ws54;
      preamt_2[64*k+54] = c*my_F_2*ws64;
      preamt_2[64*k+55] = c*my_F_2*ws74;
      preamt_2[64*k+56] = c*my_F_2*ws84;
      preamt_2[64*k+57] = c*my_F_2*ws94;
      preamt_2[64*k+58] = c*my_F_2*wsa4;
      preamt_2[64*k+59] = c*my_F_2*wsb4;
      preamt_2[64*k+60] = c*my_F_2*wsc4;
      preamt_2[64*k+61] = c*my_F_2*wsd4;
      preamt_2[64*k+62] = c*my_F_2*wse4;
      preamt_2[64*k+63] = c*my_F_2*wsf4;

      preind_2[64*k+0] = ind_1x+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+1] = ind_1y+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+2] = ind_1z+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+3] = ind_1w+N1*ind_2x+N1*N2*ind_3x; 
      preind_2[64*k+4] = ind_1x+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+5] = ind_1y+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+6] = ind_1z+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+7] = ind_1w+N1*ind_2y+N1*N2*ind_3x; 
      preind_2[64*k+8] = ind_1x+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+9] = ind_1y+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+10] = ind_1z+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+11] = ind_1w+N1*ind_2z+N1*N2*ind_3x; 
      preind_2[64*k+12] = ind_1x+N1*ind_2w+N1*N2*ind_3x; 
      preind_2[64*k+13] = ind_1y+N1*ind_2w+N1*N2*ind_3x; 
      preind_2[64*k+14] = ind_1z+N1*ind_2w+N1*N2*ind_3x; 
      preind_2[64*k+15] = ind_1w+N1*ind_2w+N1*N2*ind_3x; 

      preind_2[64*k+16] = ind_1x+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+17] = ind_1y+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+18] = ind_1z+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+19] = ind_1w+N1*ind_2x+N1*N2*ind_3y; 
      preind_2[64*k+20] = ind_1x+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+21] = ind_1y+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+22] = ind_1z+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+23] = ind_1w+N1*ind_2y+N1*N2*ind_3y; 
      preind_2[64*k+24] = ind_1x+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+25] = ind_1y+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+26] = ind_1z+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+27] = ind_1w+N1*ind_2z+N1*N2*ind_3y; 
      preind_2[64*k+28] = ind_1x+N1*ind_2w+N1*N2*ind_3y; 
      preind_2[64*k+29] = ind_1y+N1*ind_2w+N1*N2*ind_3y; 
      preind_2[64*k+30] = ind_1z+N1*ind_2w+N1*N2*ind_3y; 
      preind_2[64*k+31] = ind_1w+N1*ind_2w+N1*N2*ind_3y; 

      preind_2[64*k+32] = ind_1x+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+33] = ind_1y+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+34] = ind_1z+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+35] = ind_1w+N1*ind_2x+N1*N2*ind_3z; 
      preind_2[64*k+36] = ind_1x+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+37] = ind_1y+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+38] = ind_1z+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+39] = ind_1w+N1*ind_2y+N1*N2*ind_3z; 
      preind_2[64*k+40] = ind_1x+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+41] = ind_1y+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+42] = ind_1z+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+43] = ind_1w+N1*ind_2z+N1*N2*ind_3z; 
      preind_2[64*k+44] = ind_1x+N1*ind_2w+N1*N2*ind_3z; 
      preind_2[64*k+45] = ind_1y+N1*ind_2w+N1*N2*ind_3z; 
      preind_2[64*k+46] = ind_1z+N1*ind_2w+N1*N2*ind_3z; 
      preind_2[64*k+47] = ind_1w+N1*ind_2w+N1*N2*ind_3z; 

      preind_2[64*k+48] = ind_1x+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+49] = ind_1y+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+50] = ind_1z+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+51] = ind_1w+N1*ind_2x+N1*N2*ind_3w; 
      preind_2[64*k+52] = ind_1x+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+53] = ind_1y+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+54] = ind_1z+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+55] = ind_1w+N1*ind_2y+N1*N2*ind_3w; 
      preind_2[64*k+56] = ind_1x+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+57] = ind_1y+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+58] = ind_1z+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+59] = ind_1w+N1*ind_2z+N1*N2*ind_3w; 
      preind_2[64*k+60] = ind_1x+N1*ind_2w+N1*N2*ind_3w; 
      preind_2[64*k+61] = ind_1y+N1*ind_2w+N1*N2*ind_3w; 
      preind_2[64*k+62] = ind_1z+N1*ind_2w+N1*N2*ind_3w; 
      preind_2[64*k+63] = ind_1w+N1*ind_2w+N1*N2*ind_3w; 

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_stag-1 & N3-1);
      ind_3y = (i_3_stag & N3-1);
      ind_3z = (i_3_stag+1 & N3-1);
      ind_3w = (i_3_stag+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k];
      preamt_3[64*k+0] = c*my_F_3*ws01;
      preamt_3[64*k+1] = c*my_F_3*ws11;
      preamt_3[64*k+2] = c*my_F_3*ws21;
      preamt_3[64*k+3] = c*my_F_3*ws31;
      preamt_3[64*k+4] = c*my_F_3*ws41;
      preamt_3[64*k+5] = c*my_F_3*ws51;
      preamt_3[64*k+6] = c*my_F_3*ws61;
      preamt_3[64*k+7] = c*my_F_3*ws71;
      preamt_3[64*k+8] = c*my_F_3*ws81;
      preamt_3[64*k+9] = c*my_F_3*ws91;
      preamt_3[64*k+10] = c*my_F_3*wsa1;
      preamt_3[64*k+11] = c*my_F_3*wsb1;
      preamt_3[64*k+12] = c*my_F_3*wsc1;
      preamt_3[64*k+13] = c*my_F_3*wsd1;
      preamt_3[64*k+14] = c*my_F_3*wse1;
      preamt_3[64*k+15] = c*my_F_3*wsf1;

      preamt_3[64*k+16] = c*my_F_3*ws02;
      preamt_3[64*k+17] = c*my_F_3*ws12;
      preamt_3[64*k+18] = c*my_F_3*ws22;
      preamt_3[64*k+19] = c*my_F_3*ws32;
      preamt_3[64*k+20] = c*my_F_3*ws42;
      preamt_3[64*k+21] = c*my_F_3*ws52;
      preamt_3[64*k+22] = c*my_F_3*ws62;
      preamt_3[64*k+23] = c*my_F_3*ws72;
      preamt_3[64*k+24] = c*my_F_3*ws82;
      preamt_3[64*k+25] = c*my_F_3*ws92;
      preamt_3[64*k+26] = c*my_F_3*wsa2;
      preamt_3[64*k+27] = c*my_F_3*wsb2;
      preamt_3[64*k+28] = c*my_F_3*wsc2;
      preamt_3[64*k+29] = c*my_F_3*wsd2;
      preamt_3[64*k+30] = c*my_F_3*wse2;
      preamt_3[64*k+31] = c*my_F_3*wsf2;

      preamt_3[64*k+32] = c*my_F_3*ws03;
      preamt_3[64*k+33] = c*my_F_3*ws13;
      preamt_3[64*k+34] = c*my_F_3*ws23;
      preamt_3[64*k+35] = c*my_F_3*ws33;
      preamt_3[64*k+36] = c*my_F_3*ws43;
      preamt_3[64*k+37] = c*my_F_3*ws53;
      preamt_3[64*k+38] = c*my_F_3*ws63;
      preamt_3[64*k+39] = c*my_F_3*ws73;
      preamt_3[64*k+40] = c*my_F_3*ws83;
      preamt_3[64*k+41] = c*my_F_3*ws93;
      preamt_3[64*k+42] = c*my_F_3*wsa3;
      preamt_3[64*k+43] = c*my_F_3*wsb3;
      preamt_3[64*k+44] = c*my_F_3*wsc3;
      preamt_3[64*k+45] = c*my_F_3*wsd3;
      preamt_3[64*k+46] = c*my_F_3*wse3;
      preamt_3[64*k+47] = c*my_F_3*wsf3;

      preamt_3[64*k+48] = c*my_F_3*ws04;
      preamt_3[64*k+49] = c*my_F_3*ws14;
      preamt_3[64*k+50] = c*my_F_3*ws24;
      preamt_3[64*k+51] = c*my_F_3*ws34;
      preamt_3[64*k+52] = c*my_F_3*ws44;
      preamt_3[64*k+53] = c*my_F_3*ws54;
      preamt_3[64*k+54] = c*my_F_3*ws64;
      preamt_3[64*k+55] = c*my_F_3*ws74;
      preamt_3[64*k+56] = c*my_F_3*ws84;
      preamt_3[64*k+57] = c*my_F_3*ws94;
      preamt_3[64*k+58] = c*my_F_3*wsa4;
      preamt_3[64*k+59] = c*my_F_3*wsb4;
      preamt_3[64*k+60] = c*my_F_3*wsc4;
      preamt_3[64*k+61] = c*my_F_3*wsd4;
      preamt_3[64*k+62] = c*my_F_3*wse4;
      preamt_3[64*k+63] = c*my_F_3*wsf4;

      preind_3[64*k+0] = ind_1x+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+1] = ind_1y+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+2] = ind_1z+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+3] = ind_1w+N1*ind_2x+N1*N2*ind_3x; 
      preind_3[64*k+4] = ind_1x+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+5] = ind_1y+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+6] = ind_1z+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+7] = ind_1w+N1*ind_2y+N1*N2*ind_3x; 
      preind_3[64*k+8] = ind_1x+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+9] = ind_1y+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+10] = ind_1z+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+11] = ind_1w+N1*ind_2z+N1*N2*ind_3x; 
      preind_3[64*k+12] = ind_1x+N1*ind_2w+N1*N2*ind_3x; 
      preind_3[64*k+13] = ind_1y+N1*ind_2w+N1*N2*ind_3x; 
      preind_3[64*k+14] = ind_1z+N1*ind_2w+N1*N2*ind_3x; 
      preind_3[64*k+15] = ind_1w+N1*ind_2w+N1*N2*ind_3x; 

      preind_3[64*k+16] = ind_1x+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+17] = ind_1y+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+18] = ind_1z+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+19] = ind_1w+N1*ind_2x+N1*N2*ind_3y; 
      preind_3[64*k+20] = ind_1x+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+21] = ind_1y+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+22] = ind_1z+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+23] = ind_1w+N1*ind_2y+N1*N2*ind_3y; 
      preind_3[64*k+24] = ind_1x+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+25] = ind_1y+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+26] = ind_1z+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+27] = ind_1w+N1*ind_2z+N1*N2*ind_3y; 
      preind_3[64*k+28] = ind_1x+N1*ind_2w+N1*N2*ind_3y; 
      preind_3[64*k+29] = ind_1y+N1*ind_2w+N1*N2*ind_3y; 
      preind_3[64*k+30] = ind_1z+N1*ind_2w+N1*N2*ind_3y; 
      preind_3[64*k+31] = ind_1w+N1*ind_2w+N1*N2*ind_3y; 

      preind_3[64*k+32] = ind_1x+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+33] = ind_1y+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+34] = ind_1z+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+35] = ind_1w+N1*ind_2x+N1*N2*ind_3z; 
      preind_3[64*k+36] = ind_1x+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+37] = ind_1y+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+38] = ind_1z+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+39] = ind_1w+N1*ind_2y+N1*N2*ind_3z; 
      preind_3[64*k+40] = ind_1x+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+41] = ind_1y+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+42] = ind_1z+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+43] = ind_1w+N1*ind_2z+N1*N2*ind_3z; 
      preind_3[64*k+44] = ind_1x+N1*ind_2w+N1*N2*ind_3z; 
      preind_3[64*k+45] = ind_1y+N1*ind_2w+N1*N2*ind_3z; 
      preind_3[64*k+46] = ind_1z+N1*ind_2w+N1*N2*ind_3z; 
      preind_3[64*k+47] = ind_1w+N1*ind_2w+N1*N2*ind_3z; 

      preind_3[64*k+48] = ind_1x+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+49] = ind_1y+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+50] = ind_1z+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+51] = ind_1w+N1*ind_2x+N1*N2*ind_3w; 
      preind_3[64*k+52] = ind_1x+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+53] = ind_1y+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+54] = ind_1z+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+55] = ind_1w+N1*ind_2y+N1*N2*ind_3w; 
      preind_3[64*k+56] = ind_1x+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+57] = ind_1y+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+58] = ind_1z+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+59] = ind_1w+N1*ind_2z+N1*N2*ind_3w; 
      preind_3[64*k+60] = ind_1x+N1*ind_2w+N1*N2*ind_3w; 
      preind_3[64*k+61] = ind_1y+N1*ind_2w+N1*N2*ind_3w; 
      preind_3[64*k+62] = ind_1z+N1*ind_2w+N1*N2*ind_3w; 
      preind_3[64*k+63] = ind_1w+N1*ind_2w+N1*N2*ind_3w; 
    }
    __kernel void spread_local(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, const unsigned shift0, const unsigned shift1, const unsigned shift2, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      unsigned k = 4*get_global_id(2)+shift2;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      int k1 = firstn1[i+N1*j+N1*N2*k]; 
      int k2 = firstn2[i+N1*j+N1*N2*k]; 
      int k3 = firstn3[i+N1*j+N1*N2*k]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      if (k1 !=-1){
      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      f_01=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      f_11=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      f_21=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      f_31=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      f_41=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      f_51=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      f_61=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      f_71=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      f_81=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      f_91=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      f_a1=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      f_b1=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      f_c1=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      f_d1=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      f_e1=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      f_f1=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      f_02=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      f_12=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      f_22=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      f_32=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      f_42=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      f_52=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      f_62=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      f_72=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      f_82=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      f_92=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      f_a2=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      f_b2=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      f_c2=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      f_d2=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      f_e2=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      f_f2=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      f_03=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      f_13=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      f_23=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      f_33=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      f_43=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      f_53=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      f_63=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      f_73=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      f_83=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      f_93=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      f_a3=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      f_b3=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      f_c3=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      f_d3=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      f_e3=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      f_f3=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      f_04=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      f_14=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      f_24=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      f_34=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      f_44=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      f_54=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      f_64=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      f_74=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      f_84=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      f_94=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      f_a4=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      f_b4=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      f_c4=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      f_d4=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      f_e4=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      f_f4=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w];
      }
 
      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k1]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k1]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k1];
      f_01 += c*my_F_1*ws01;
      f_11 += c*my_F_1*ws11;
      f_21 += c*my_F_1*ws21;
      f_31 += c*my_F_1*ws31;
      f_41 += c*my_F_1*ws41;
      f_51 += c*my_F_1*ws51;
      f_61 += c*my_F_1*ws61;
      f_71 += c*my_F_1*ws71;
      f_81 += c*my_F_1*ws81;
      f_91 += c*my_F_1*ws91;
      f_a1 += c*my_F_1*wsa1;
      f_b1 += c*my_F_1*wsb1;
      f_c1 += c*my_F_1*wsc1;
      f_d1 += c*my_F_1*wsd1;
      f_e1 += c*my_F_1*wse1;
      f_f1 += c*my_F_1*wsf1;

      f_02 += c*my_F_1*ws02;
      f_12 += c*my_F_1*ws12;
      f_22 += c*my_F_1*ws22;
      f_32 += c*my_F_1*ws32;
      f_42 += c*my_F_1*ws42;
      f_52 += c*my_F_1*ws52;
      f_62 += c*my_F_1*ws62;
      f_72 += c*my_F_1*ws72;
      f_82 += c*my_F_1*ws82;
      f_92 += c*my_F_1*ws92;
      f_a2 += c*my_F_1*wsa2;
      f_b2 += c*my_F_1*wsb2;
      f_c2 += c*my_F_1*wsc2;
      f_d2 += c*my_F_1*wsd2;
      f_e2 += c*my_F_1*wse2;
      f_f2 += c*my_F_1*wsf2;

      f_03 += c*my_F_1*ws03;
      f_13 += c*my_F_1*ws13;
      f_23 += c*my_F_1*ws23;
      f_33 += c*my_F_1*ws33;
      f_43 += c*my_F_1*ws43;
      f_53 += c*my_F_1*ws53;
      f_63 += c*my_F_1*ws63;
      f_73 += c*my_F_1*ws73;
      f_83 += c*my_F_1*ws83;
      f_93 += c*my_F_1*ws93;
      f_a3 += c*my_F_1*wsa3;
      f_b3 += c*my_F_1*wsb3;
      f_c3 += c*my_F_1*wsc3;
      f_d3 += c*my_F_1*wsd3;
      f_e3 += c*my_F_1*wse3;
      f_f3 += c*my_F_1*wsf3;

      f_04 += c*my_F_1*ws04;
      f_14 += c*my_F_1*ws14;
      f_24 += c*my_F_1*ws24;
      f_34 += c*my_F_1*ws34;
      f_44 += c*my_F_1*ws44;
      f_54 += c*my_F_1*ws54;
      f_64 += c*my_F_1*ws64;
      f_74 += c*my_F_1*ws74;
      f_84 += c*my_F_1*ws84;
      f_94 += c*my_F_1*ws94;
      f_a4 += c*my_F_1*wsa4;
      f_b4 += c*my_F_1*wsb4;
      f_c4 += c*my_F_1*wsc4;
      f_d4 += c*my_F_1*wsd4;
      f_e4 += c*my_F_1*wse4;
      f_f4 += c*my_F_1*wsf4;

      k1 = nextn1[k1];
      if (k1 == -1){
      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x]=f_01;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x]=f_11;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x]=f_21;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x]=f_31;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x]=f_41;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x]=f_51;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x]=f_61;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x]=f_71;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x]=f_81;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x]=f_91;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x]=f_a1;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x]=f_b1;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x]=f_c1;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x]=f_d1;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x]=f_e1;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x]=f_f1;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y]=f_02;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y]=f_12;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y]=f_22;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y]=f_32;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y]=f_42;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y]=f_52;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y]=f_62;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y]=f_72;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y]=f_82;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y]=f_92;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y]=f_a2;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y]=f_b2;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y]=f_c2;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y]=f_d2;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y]=f_e2;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y]=f_f2;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z]=f_03;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z]=f_13;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z]=f_23;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z]=f_33;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z]=f_43;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z]=f_53;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z]=f_63;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z]=f_73;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z]=f_83;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z]=f_93;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z]=f_a3;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z]=f_b3;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z]=f_c3;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z]=f_d3;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z]=f_e3;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z]=f_f3;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w]=f_04;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w]=f_14;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w]=f_24;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w]=f_34;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w]=f_44;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w]=f_54;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w]=f_64;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w]=f_74;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w]=f_84;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w]=f_94;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w]=f_a4;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w]=f_b4;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w]=f_c4;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w]=f_d4;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w]=f_e4;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w]=f_f4;
      }
      }

      if (k2 !=-1){
      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      f_01=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      f_11=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      f_21=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      f_31=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      f_41=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      f_51=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      f_61=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      f_71=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      f_81=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      f_91=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      f_a1=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      f_b1=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      f_c1=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      f_d1=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      f_e1=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      f_f1=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      f_02=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      f_12=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      f_22=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      f_32=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      f_42=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      f_52=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      f_62=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      f_72=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      f_82=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      f_92=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      f_a2=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      f_b2=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      f_c2=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      f_d2=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      f_e2=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      f_f2=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      f_03=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      f_13=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      f_23=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      f_33=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      f_43=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      f_53=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      f_63=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      f_73=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      f_83=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      f_93=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      f_a3=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      f_b3=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      f_c3=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      f_d3=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      f_e3=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      f_f3=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      f_04=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      f_14=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      f_24=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      f_34=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      f_44=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      f_54=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      f_64=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      f_74=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      f_84=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      f_94=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      f_a4=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      f_b4=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      f_c4=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      f_d4=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      f_e4=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      f_f4=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w];
      }
 
      while(k2 != -1)
      {
      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k2]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k2];
      f_01 += c*my_F_2*ws01;
      f_11 += c*my_F_2*ws11;
      f_21 += c*my_F_2*ws21;
      f_31 += c*my_F_2*ws31;
      f_41 += c*my_F_2*ws41;
      f_51 += c*my_F_2*ws51;
      f_61 += c*my_F_2*ws61;
      f_71 += c*my_F_2*ws71;
      f_81 += c*my_F_2*ws81;
      f_91 += c*my_F_2*ws91;
      f_a1 += c*my_F_2*wsa1;
      f_b1 += c*my_F_2*wsb1;
      f_c1 += c*my_F_2*wsc1;
      f_d1 += c*my_F_2*wsd1;
      f_e1 += c*my_F_2*wse1;
      f_f1 += c*my_F_2*wsf1;

      f_02 += c*my_F_2*ws02;
      f_12 += c*my_F_2*ws12;
      f_22 += c*my_F_2*ws22;
      f_32 += c*my_F_2*ws32;
      f_42 += c*my_F_2*ws42;
      f_52 += c*my_F_2*ws52;
      f_62 += c*my_F_2*ws62;
      f_72 += c*my_F_2*ws72;
      f_82 += c*my_F_2*ws82;
      f_92 += c*my_F_2*ws92;
      f_a2 += c*my_F_2*wsa2;
      f_b2 += c*my_F_2*wsb2;
      f_c2 += c*my_F_2*wsc2;
      f_d2 += c*my_F_2*wsd2;
      f_e2 += c*my_F_2*wse2;
      f_f2 += c*my_F_2*wsf2;

      f_03 += c*my_F_2*ws03;
      f_13 += c*my_F_2*ws13;
      f_23 += c*my_F_2*ws23;
      f_33 += c*my_F_2*ws33;
      f_43 += c*my_F_2*ws43;
      f_53 += c*my_F_2*ws53;
      f_63 += c*my_F_2*ws63;
      f_73 += c*my_F_2*ws73;
      f_83 += c*my_F_2*ws83;
      f_93 += c*my_F_2*ws93;
      f_a3 += c*my_F_2*wsa3;
      f_b3 += c*my_F_2*wsb3;
      f_c3 += c*my_F_2*wsc3;
      f_d3 += c*my_F_2*wsd3;
      f_e3 += c*my_F_2*wse3;
      f_f3 += c*my_F_2*wsf3;

      f_04 += c*my_F_2*ws04;
      f_14 += c*my_F_2*ws14;
      f_24 += c*my_F_2*ws24;
      f_34 += c*my_F_2*ws34;
      f_44 += c*my_F_2*ws44;
      f_54 += c*my_F_2*ws54;
      f_64 += c*my_F_2*ws64;
      f_74 += c*my_F_2*ws74;
      f_84 += c*my_F_2*ws84;
      f_94 += c*my_F_2*ws94;
      f_a4 += c*my_F_2*wsa4;
      f_b4 += c*my_F_2*wsb4;
      f_c4 += c*my_F_2*wsc4;
      f_d4 += c*my_F_2*wsd4;
      f_e4 += c*my_F_2*wse4;
      f_f4 += c*my_F_2*wsf4;

      k2 = nextn2[k2];
      if (k2 == -1){
      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x]=f_01;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x]=f_11;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x]=f_21;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x]=f_31;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x]=f_41;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x]=f_51;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x]=f_61;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x]=f_71;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x]=f_81;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x]=f_91;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x]=f_a1;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x]=f_b1;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x]=f_c1;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x]=f_d1;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x]=f_e1;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x]=f_f1;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y]=f_02;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y]=f_12;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y]=f_22;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y]=f_32;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y]=f_42;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y]=f_52;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y]=f_62;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y]=f_72;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y]=f_82;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y]=f_92;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y]=f_a2;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y]=f_b2;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y]=f_c2;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y]=f_d2;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y]=f_e2;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y]=f_f2;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z]=f_03;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z]=f_13;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z]=f_23;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z]=f_33;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z]=f_43;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z]=f_53;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z]=f_63;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z]=f_73;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z]=f_83;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z]=f_93;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z]=f_a3;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z]=f_b3;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z]=f_c3;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z]=f_d3;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z]=f_e3;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z]=f_f3;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w]=f_04;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w]=f_14;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w]=f_24;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w]=f_34;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w]=f_44;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w]=f_54;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w]=f_64;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w]=f_74;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w]=f_84;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w]=f_94;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w]=f_a4;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w]=f_b4;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w]=f_c4;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w]=f_d4;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w]=f_e4;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w]=f_f4;
      }
      }

      if (k3 !=-1){
      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      f_01=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      f_11=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      f_21=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      f_31=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      f_41=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      f_51=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      f_61=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      f_71=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      f_81=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      f_91=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      f_a1=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      f_b1=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      f_c1=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      f_d1=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      f_e1=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      f_f1=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      f_02=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      f_12=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      f_22=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      f_32=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      f_42=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      f_52=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      f_62=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      f_72=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      f_82=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      f_92=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      f_a2=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      f_b2=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      f_c2=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      f_d2=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      f_e2=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      f_f2=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      f_03=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      f_13=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      f_23=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      f_33=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      f_43=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      f_53=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      f_63=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      f_73=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      f_83=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      f_93=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      f_a3=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      f_b3=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      f_c3=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      f_d3=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      f_e3=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      f_f3=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      f_04=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      f_14=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      f_24=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      f_34=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      f_44=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      f_54=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      f_64=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      f_74=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      f_84=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      f_94=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      f_a4=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      f_b4=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      f_c4=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      f_d4=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      f_e4=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      f_f4=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w];
      }
 
      while(k3 != -1)
      {
      float s_1_stag = (X_1[k3]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k3]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k3];
      f_01 += c*my_F_3*ws01;
      f_11 += c*my_F_3*ws11;
      f_21 += c*my_F_3*ws21;
      f_31 += c*my_F_3*ws31;
      f_41 += c*my_F_3*ws41;
      f_51 += c*my_F_3*ws51;
      f_61 += c*my_F_3*ws61;
      f_71 += c*my_F_3*ws71;
      f_81 += c*my_F_3*ws81;
      f_91 += c*my_F_3*ws91;
      f_a1 += c*my_F_3*wsa1;
      f_b1 += c*my_F_3*wsb1;
      f_c1 += c*my_F_3*wsc1;
      f_d1 += c*my_F_3*wsd1;
      f_e1 += c*my_F_3*wse1;
      f_f1 += c*my_F_3*wsf1;

      f_02 += c*my_F_3*ws02;
      f_12 += c*my_F_3*ws12;
      f_22 += c*my_F_3*ws22;
      f_32 += c*my_F_3*ws32;
      f_42 += c*my_F_3*ws42;
      f_52 += c*my_F_3*ws52;
      f_62 += c*my_F_3*ws62;
      f_72 += c*my_F_3*ws72;
      f_82 += c*my_F_3*ws82;
      f_92 += c*my_F_3*ws92;
      f_a2 += c*my_F_3*wsa2;
      f_b2 += c*my_F_3*wsb2;
      f_c2 += c*my_F_3*wsc2;
      f_d2 += c*my_F_3*wsd2;
      f_e2 += c*my_F_3*wse2;
      f_f2 += c*my_F_3*wsf2;

      f_03 += c*my_F_3*ws03;
      f_13 += c*my_F_3*ws13;
      f_23 += c*my_F_3*ws23;
      f_33 += c*my_F_3*ws33;
      f_43 += c*my_F_3*ws43;
      f_53 += c*my_F_3*ws53;
      f_63 += c*my_F_3*ws63;
      f_73 += c*my_F_3*ws73;
      f_83 += c*my_F_3*ws83;
      f_93 += c*my_F_3*ws93;
      f_a3 += c*my_F_3*wsa3;
      f_b3 += c*my_F_3*wsb3;
      f_c3 += c*my_F_3*wsc3;
      f_d3 += c*my_F_3*wsd3;
      f_e3 += c*my_F_3*wse3;
      f_f3 += c*my_F_3*wsf3;

      f_04 += c*my_F_3*ws04;
      f_14 += c*my_F_3*ws14;
      f_24 += c*my_F_3*ws24;
      f_34 += c*my_F_3*ws34;
      f_44 += c*my_F_3*ws44;
      f_54 += c*my_F_3*ws54;
      f_64 += c*my_F_3*ws64;
      f_74 += c*my_F_3*ws74;
      f_84 += c*my_F_3*ws84;
      f_94 += c*my_F_3*ws94;
      f_a4 += c*my_F_3*wsa4;
      f_b4 += c*my_F_3*wsb4;
      f_c4 += c*my_F_3*wsc4;
      f_d4 += c*my_F_3*wsd4;
      f_e4 += c*my_F_3*wse4;
      f_f4 += c*my_F_3*wsf4;

      k3 = nextn3[k3];
      if (k3 == -1){
      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x]=f_01;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x]=f_11;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x]=f_21;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x]=f_31;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x]=f_41;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x]=f_51;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x]=f_61;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x]=f_71;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x]=f_81;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x]=f_91;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x]=f_a1;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x]=f_b1;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x]=f_c1;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x]=f_d1;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x]=f_e1;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x]=f_f1;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y]=f_02;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y]=f_12;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y]=f_22;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y]=f_32;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y]=f_42;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y]=f_52;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y]=f_62;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y]=f_72;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y]=f_82;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y]=f_92;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y]=f_a2;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y]=f_b2;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y]=f_c2;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y]=f_d2;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y]=f_e2;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y]=f_f2;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z]=f_03;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z]=f_13;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z]=f_23;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z]=f_33;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z]=f_43;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z]=f_53;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z]=f_63;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z]=f_73;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z]=f_83;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z]=f_93;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z]=f_a3;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z]=f_b3;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z]=f_c3;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z]=f_d3;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z]=f_e3;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z]=f_f3;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w]=f_04;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w]=f_14;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w]=f_24;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w]=f_34;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w]=f_44;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w]=f_54;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w]=f_64;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w]=f_74;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w]=f_84;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w]=f_94;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w]=f_a4;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w]=f_b4;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w]=f_c4;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w]=f_d4;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w]=f_e4;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w]=f_f4;
      }
      }
    }
    __kernel void spread_serial(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, const unsigned kk, const unsigned shift1, const unsigned shift2, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      float s_1_stag, s_2_stag, s_3_stag; 
      float r_1_stag, r_2_stag, r_3_stag; 
      float s_1_c, s_2_c, s_3_c; 
      float r_1_c, r_2_c, r_3_c; 
      int i_1_stag, i_2_stag, i_3_stag;
      int i_1_c, i_2_c, i_3_c;

      s_1_stag = (X_1[kk]+L1*0.5)/dx1;
      s_2_stag = (X_2[kk]+L2*0.5)/dx2;       
      s_3_stag = (X_3[kk]+L3*0.5)/dx3;       
      i_1_stag = convert_int(floor(s_1_stag));
      i_2_stag = convert_int(floor(s_2_stag));
      i_3_stag = convert_int(floor(s_3_stag));
      r_1_stag = s_1_stag-i_1_stag;
      r_2_stag = s_2_stag-i_2_stag;
      r_3_stag = s_3_stag-i_3_stag;
      s_1_c = (X_1[kk]+L1*0.5-dx1/2.0)/dx1;
      s_2_c = (X_2[kk]+L2*0.5-dx2/2.0)/dx2;        
      s_3_c = (X_3[kk]+L3*0.5-dx3/2.0)/dx3;        
      i_1_c = convert_int(floor(s_1_c));
      i_2_c = convert_int(floor(s_2_c));
      i_3_c = convert_int(floor(s_3_c));
      r_1_c = s_1_c-i_1_c;
      r_2_c = s_2_c-i_2_c;
      r_3_c = s_3_c-i_3_c;

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      float my_F_1 = F_1[kk];
      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws01;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws11;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws21;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws31;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws41;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws51;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws61;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws71;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*ws81;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*ws91;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*wsa1;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*wsb1;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsc1;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsd1;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wse1;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsf1;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws02;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws12;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws22;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws32;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws42;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws52;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws62;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws72;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*ws82;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*ws92;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*wsa2;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*wsb2;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsc2;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsd2;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wse2;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsf2;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws03;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws13;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws23;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws33;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws43;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws53;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws63;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws73;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*ws83;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*ws93;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*wsa3;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*wsb3;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsc3;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsd3;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wse3;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsf3;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws04;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws14;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws24;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws34;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws44;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws54;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws64;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws74;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*ws84;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*ws94;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*wsa4;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*wsb4;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsc4;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsd4;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wse4;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsf4;

      s_1_stag = (X_1[kk]+L1*0.5)/dx1;
      s_2_stag = (X_2[kk]+L2*0.5)/dx2;       
      s_3_stag = (X_3[kk]+L3*0.5)/dx3;       
      i_1_stag = convert_int(floor(s_1_stag));
      i_2_stag = convert_int(floor(s_2_stag));
      i_3_stag = convert_int(floor(s_3_stag));
      r_1_stag = s_1_stag-i_1_stag;
      r_2_stag = s_2_stag-i_2_stag;
      r_3_stag = s_3_stag-i_3_stag;
      s_1_c = (X_1[kk]+L1*0.5-dx1/2.0)/dx1;
      s_2_c = (X_2[kk]+L2*0.5-dx2/2.0)/dx2;        
      s_3_c = (X_3[kk]+L3*0.5-dx3/2.0)/dx3;        
      i_1_c = convert_int(floor(s_1_c));
      i_2_c = convert_int(floor(s_2_c));
      i_3_c = convert_int(floor(s_3_c));
      r_1_c = s_1_c-i_1_c;
      r_2_c = s_2_c-i_2_c;
      r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_stag-1 & N2-1);
      ind_2y = (i_2_stag & N2-1);
      ind_2z = (i_2_stag+1 & N2-1);
      ind_2w = (i_2_stag+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      float my_F_2 = F_2[kk];
      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws01;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws11;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws21;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws31;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws41;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws51;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws61;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws71;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*ws81;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*ws91;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*wsa1;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*wsb1;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsc1;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsd1;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wse1;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsf1;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws02;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws12;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws22;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws32;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws42;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws52;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws62;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws72;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*ws82;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*ws92;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*wsa2;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*wsb2;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsc2;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsd2;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wse2;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsf2;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws03;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws13;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws23;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws33;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws43;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws53;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws63;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws73;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*ws83;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*ws93;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*wsa3;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*wsb3;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsc3;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsd3;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wse3;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsf3;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws04;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws14;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws24;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws34;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws44;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws54;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws64;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws74;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*ws84;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*ws94;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*wsa4;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*wsb4;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsc4;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsd4;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wse4;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsf4;

      s_1_stag = (X_1[kk]+L1*0.5)/dx1;
      s_2_stag = (X_2[kk]+L2*0.5)/dx2;       
      s_3_stag = (X_3[kk]+L3*0.5)/dx3;       
      i_1_stag = convert_int(floor(s_1_stag));
      i_2_stag = convert_int(floor(s_2_stag));
      i_3_stag = convert_int(floor(s_3_stag));
      r_1_stag = s_1_stag-i_1_stag;
      r_2_stag = s_2_stag-i_2_stag;
      r_3_stag = s_3_stag-i_3_stag;
      s_1_c = (X_1[kk]+L1*0.5-dx1/2.0)/dx1;
      s_2_c = (X_2[kk]+L2*0.5-dx2/2.0)/dx2;        
      s_3_c = (X_3[kk]+L3*0.5-dx3/2.0)/dx3;        
      i_1_c = convert_int(floor(s_1_c));
      i_2_c = convert_int(floor(s_2_c));
      i_3_c = convert_int(floor(s_3_c));
      r_1_c = s_1_c-i_1_c;
      r_2_c = s_2_c-i_2_c;
      r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_stag-1 & N3-1);
      ind_3y = (i_3_stag & N3-1);
      ind_3z = (i_3_stag+1 & N3-1);
      ind_3w = (i_3_stag+2 & N3-1);

      float my_F_3 = F_3[kk];
      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws01;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws11;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws21;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws31;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws41;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws51;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws61;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws71;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*ws81;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*ws91;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*wsa1;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*wsb1;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsc1;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsd1;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wse1;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsf1;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws02;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws12;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws22;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws32;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws42;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws52;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws62;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws72;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*ws82;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*ws92;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*wsa2;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*wsb2;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsc2;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsd2;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wse2;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsf2;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws03;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws13;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws23;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws33;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws43;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws53;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws63;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws73;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*ws83;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*ws93;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*wsa3;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*wsb3;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsc3;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsd3;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wse3;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsf3;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws04;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws14;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws24;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws34;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws44;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws54;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws64;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws74;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*ws84;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*ws94;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*wsa4;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*wsb4;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsc4;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsd4;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wse4;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsf4;
    }
    __kernel void spread_simple(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, const unsigned shift0, const unsigned shift1, const unsigned shift2, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      unsigned k = 4*get_global_id(2)+shift2;
      //k = 76;
      //j = 41;
      //i = 38;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      int k1 = firstn1[i+N1*j+N1*N2*k]; 
      int k2 = firstn2[i+N1*j+N1*N2*k]; 
      int k3 = firstn3[i+N1*j+N1*N2*k]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k1]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k1]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k1];
      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws01;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws11;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws21;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws31;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws41;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws51;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws61;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws71;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*ws81;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*ws91;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*wsa1;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*wsb1;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsc1;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsd1;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wse1;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsf1;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws02;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws12;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws22;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws32;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws42;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws52;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws62;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws72;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*ws82;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*ws92;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*wsa2;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*wsb2;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsc2;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsd2;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wse2;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsf2;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws03;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws13;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws23;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws33;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws43;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws53;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws63;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws73;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*ws83;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*ws93;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*wsa3;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*wsb3;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsc3;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsd3;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wse3;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsf3;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws04;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws14;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws24;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws34;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws44;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws54;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws64;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws74;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*ws84;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*ws94;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*wsa4;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*wsb4;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsc4;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsd4;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wse4;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsf4;

      k1 = nextn1[k1];
      }

      while(k2 != -1)
      {
      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k2]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k2];
      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws01;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws11;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws21;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws31;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws41;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws51;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws61;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws71;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*ws81;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*ws91;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*wsa1;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*wsb1;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsc1;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsd1;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wse1;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsf1;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws02;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws12;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws22;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws32;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws42;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws52;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws62;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws72;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*ws82;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*ws92;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*wsa2;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*wsb2;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsc2;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsd2;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wse2;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsf2;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws03;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws13;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws23;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws33;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws43;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws53;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws63;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws73;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*ws83;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*ws93;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*wsa3;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*wsb3;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsc3;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsd3;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wse3;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsf3;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws04;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws14;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws24;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws34;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws44;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws54;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws64;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws74;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*ws84;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*ws94;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*wsa4;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*wsb4;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsc4;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsd4;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wse4;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsf4;

      k2 = nextn2[k2];
      }

      while(k3 != -1)
      {
      float s_1_stag = (X_1[k3]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k3]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k3];
      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws01;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws11;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws21;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws31;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws41;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws51;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws61;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws71;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*ws81;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*ws91;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*wsa1;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*wsb1;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsc1;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsd1;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wse1;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsf1;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws02;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws12;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws22;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws32;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws42;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws52;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws62;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws72;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*ws82;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*ws92;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*wsa2;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*wsb2;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsc2;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsd2;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wse2;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsf2;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws03;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws13;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws23;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws33;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws43;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws53;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws63;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws73;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*ws83;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*ws93;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*wsa3;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*wsb3;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsc3;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsd3;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wse3;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsf3;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws04;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws14;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws24;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws34;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws44;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws54;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws64;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws74;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*ws84;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*ws94;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*wsa4;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*wsb4;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsc4;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsd4;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wse4;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsf4;

      k3 = nextn3[k3];
      }
    }
    __kernel void sum_col(__global const float *precol_1, __global const float *precol_2, __global const float *precol_3, const unsigned N1, const unsigned N2, const unsigned N3, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      unsigned k = get_global_id(2);

      unsigned ind_1x, ind_1y, ind_1z, ind_1w;
      unsigned ind_2x, ind_2y, ind_2z, ind_2w;
      unsigned ind_3x, ind_3y, ind_3z, ind_3w;

      ind_1x = (i-2 & N1-1);
      ind_1y = (i-1 & N1-1);
      ind_1z = (i & N1-1);
      ind_1w = (i+1 & N1-1);

      ind_2x = (j-2 & N2-1);
      ind_2y = (j-1 & N2-1);
      ind_2z = (j & N2-1);
      ind_2w = (j+1 & N2-1);

      f_1[i+N1*j+N1*N2*k] = precol_1[0+4*0+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2w]
                            +precol_1[1+4*0+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2w]
                            +precol_1[2+4*0+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2w]
                            +precol_1[3+4*0+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2w]
                            +precol_1[0+4*1+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2z]
                            +precol_1[1+4*1+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2z]
                            +precol_1[2+4*1+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2z]
                            +precol_1[3+4*1+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2z]
                            +precol_1[0+4*2+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2y]
                            +precol_1[1+4*2+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2y]
                            +precol_1[2+4*2+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2y]
                            +precol_1[3+4*2+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2y]
                            +precol_1[0+4*3+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2x]
                            +precol_1[1+4*3+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2x]
                            +precol_1[2+4*3+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2x]
                            +precol_1[3+4*3+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2x];

      f_2[i+N1*j+N1*N2*k] = precol_2[0+4*0+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2w]
                            +precol_2[1+4*0+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2w]
                            +precol_2[2+4*0+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2w]
                            +precol_2[3+4*0+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2w]
                            +precol_2[0+4*1+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2z]
                            +precol_2[1+4*1+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2z]
                            +precol_2[2+4*1+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2z]
                            +precol_2[3+4*1+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2z]
                            +precol_2[0+4*2+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2y]
                            +precol_2[1+4*2+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2y]
                            +precol_2[2+4*2+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2y]
                            +precol_2[3+4*2+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2y]
                            +precol_2[0+4*3+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2x]
                            +precol_2[1+4*3+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2x]
                            +precol_2[2+4*3+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2x]
                            +precol_2[3+4*3+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2x];

      f_3[i+N1*j+N1*N2*k] = precol_3[0+4*0+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2w]
                            +precol_3[1+4*0+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2w]
                            +precol_3[2+4*0+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2w]
                            +precol_3[3+4*0+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2w]
                            +precol_3[0+4*1+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2z]
                            +precol_3[1+4*1+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2z]
                            +precol_3[2+4*1+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2z]
                            +precol_3[3+4*1+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2z]
                            +precol_3[0+4*2+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2y]
                            +precol_3[1+4*2+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2y]
                            +precol_3[2+4*2+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2y]
                            +precol_3[3+4*2+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2y]
                            +precol_3[0+4*3+4*4*k+4*4*N3*ind_1w+4*4*N3*N1*ind_2x]
                            +precol_3[1+4*3+4*4*k+4*4*N3*ind_1z+4*4*N3*N1*ind_2x]
                            +precol_3[2+4*3+4*4*k+4*4*N3*ind_1y+4*4*N3*N1*ind_2x]
                            +precol_3[3+4*3+4*4*k+4*4*N3*ind_1x+4*4*N3*N1*ind_2x];

    }
    __kernel void spread_col(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, const unsigned shift0, const unsigned shift1, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      int k1 = firstn1[i+N2*j]; 
      int k2 = firstn2[i+N2*j]; 
      int k3 = firstn3[i+N2*j]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;
      int ind_1[4];
      int ind_2[4];
      int ind_3[4];

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      ind_2x = (i-1 & N2-1);
      ind_2y = (i & N2-1);
      ind_2z = (i+1 & N2-1);
      ind_2w = (i+2 & N2-1);
      ind_2[0] = (i-1 & N2-1);
      ind_2[1] = (i & N2-1);
      ind_2[2] = (i+1 & N2-1);
      ind_2[3] = (i+2 & N2-1);

      ind_3x = (j-1 & N3-1);
      ind_3y = (j & N3-1);
      ind_3z = (j+1 & N3-1);
      ind_3w = (j+2 & N3-1);
      ind_3[0] = (j-1 & N3-1);
      ind_3[1] = (j & N3-1);
      ind_3[2] = (j+1 & N3-1);
      ind_3[3] = (j+2 & N3-1);

      float f_local[4*4*MY_N1];
      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k1]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k1]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k1];
      f_local[ind_1x+N1*0+N1*4*0] += c*my_F_1*ws01;
      f_local[ind_1y+N1*0+N1*4*0] += c*my_F_1*ws11;
      f_local[ind_1z+N1*0+N1*4*0] += c*my_F_1*ws21;
      f_local[ind_1w+N1*0+N1*4*0] += c*my_F_1*ws31;
      f_local[ind_1x+N1*1+N1*4*0] += c*my_F_1*ws41;
      f_local[ind_1y+N1*1+N1*4*0] += c*my_F_1*ws51;
      f_local[ind_1z+N1*1+N1*4*0] += c*my_F_1*ws61;
      f_local[ind_1w+N1*1+N1*4*0] += c*my_F_1*ws71;
      f_local[ind_1x+N1*2+N1*4*0] += c*my_F_1*ws81;
      f_local[ind_1y+N1*2+N1*4*0] += c*my_F_1*ws91;
      f_local[ind_1z+N1*2+N1*4*0] += c*my_F_1*wsa1;
      f_local[ind_1w+N1*2+N1*4*0] += c*my_F_1*wsb1;
      f_local[ind_1x+N1*3+N1*4*0] += c*my_F_1*wsc1;
      f_local[ind_1y+N1*3+N1*4*0] += c*my_F_1*wsd1;
      f_local[ind_1z+N1*3+N1*4*0] += c*my_F_1*wse1;
      f_local[ind_1w+N1*3+N1*4*0] += c*my_F_1*wsf1;

      f_local[ind_1x+N1*0+N1*4*1] += c*my_F_1*ws02;
      f_local[ind_1y+N1*0+N1*4*1] += c*my_F_1*ws12;
      f_local[ind_1z+N1*0+N1*4*1] += c*my_F_1*ws22;
      f_local[ind_1w+N1*0+N1*4*1] += c*my_F_1*ws32;
      f_local[ind_1x+N1*1+N1*4*1] += c*my_F_1*ws42;
      f_local[ind_1y+N1*1+N1*4*1] += c*my_F_1*ws52;
      f_local[ind_1z+N1*1+N1*4*1] += c*my_F_1*ws62;
      f_local[ind_1w+N1*1+N1*4*1] += c*my_F_1*ws72;
      f_local[ind_1x+N1*2+N1*4*1] += c*my_F_1*ws82;
      f_local[ind_1y+N1*2+N1*4*1] += c*my_F_1*ws92;
      f_local[ind_1z+N1*2+N1*4*1] += c*my_F_1*wsa2;
      f_local[ind_1w+N1*2+N1*4*1] += c*my_F_1*wsb2;
      f_local[ind_1x+N1*3+N1*4*1] += c*my_F_1*wsc2;
      f_local[ind_1y+N1*3+N1*4*1] += c*my_F_1*wsd2;
      f_local[ind_1z+N1*3+N1*4*1] += c*my_F_1*wse2;
      f_local[ind_1w+N1*3+N1*4*1] += c*my_F_1*wsf2;

      f_local[ind_1x+N1*0+N1*4*2] += c*my_F_1*ws03;
      f_local[ind_1y+N1*0+N1*4*2] += c*my_F_1*ws13;
      f_local[ind_1z+N1*0+N1*4*2] += c*my_F_1*ws23;
      f_local[ind_1w+N1*0+N1*4*2] += c*my_F_1*ws33;
      f_local[ind_1x+N1*1+N1*4*2] += c*my_F_1*ws43;
      f_local[ind_1y+N1*1+N1*4*2] += c*my_F_1*ws53;
      f_local[ind_1z+N1*1+N1*4*2] += c*my_F_1*ws63;
      f_local[ind_1w+N1*1+N1*4*2] += c*my_F_1*ws73;
      f_local[ind_1x+N1*2+N1*4*2] += c*my_F_1*ws83;
      f_local[ind_1y+N1*2+N1*4*2] += c*my_F_1*ws93;
      f_local[ind_1z+N1*2+N1*4*2] += c*my_F_1*wsa3;
      f_local[ind_1w+N1*2+N1*4*2] += c*my_F_1*wsb3;
      f_local[ind_1x+N1*3+N1*4*2] += c*my_F_1*wsc3;
      f_local[ind_1y+N1*3+N1*4*2] += c*my_F_1*wsd3;
      f_local[ind_1z+N1*3+N1*4*2] += c*my_F_1*wse3;
      f_local[ind_1w+N1*3+N1*4*2] += c*my_F_1*wsf3;

      f_local[ind_1x+N1*0+N1*4*3] += c*my_F_1*ws04;
      f_local[ind_1y+N1*0+N1*4*3] += c*my_F_1*ws14;
      f_local[ind_1z+N1*0+N1*4*3] += c*my_F_1*ws24;
      f_local[ind_1w+N1*0+N1*4*3] += c*my_F_1*ws34;
      f_local[ind_1x+N1*1+N1*4*3] += c*my_F_1*ws44;
      f_local[ind_1y+N1*1+N1*4*3] += c*my_F_1*ws54;
      f_local[ind_1z+N1*1+N1*4*3] += c*my_F_1*ws64;
      f_local[ind_1w+N1*1+N1*4*3] += c*my_F_1*ws74;
      f_local[ind_1x+N1*2+N1*4*3] += c*my_F_1*ws84;
      f_local[ind_1y+N1*2+N1*4*3] += c*my_F_1*ws94;
      f_local[ind_1z+N1*2+N1*4*3] += c*my_F_1*wsa4;
      f_local[ind_1w+N1*2+N1*4*3] += c*my_F_1*wsb4;
      f_local[ind_1x+N1*3+N1*4*3] += c*my_F_1*wsc4;
      f_local[ind_1y+N1*3+N1*4*3] += c*my_F_1*wsd4;
      f_local[ind_1z+N1*3+N1*4*3] += c*my_F_1*wse4;
      f_local[ind_1w+N1*3+N1*4*3] += c*my_F_1*wsf4;

      k1 = nextn1[k1];
      if (k1 == -1){
      for (unsigned kk = 0; kk<4; kk++) {
      for (unsigned jj = 0; jj<4; jj++) {
      for (unsigned ii = 0; ii<N1; ii++) {
         f_1[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]] += f_local[ii+N1*jj+N1*4*kk];
      //   //f_1[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]] = f_1[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]]+f_local[ii+N1*jj+N1*4*kk];
      }
      }
      }
      }
      }

      while(k2 != -1)
      {
      for (unsigned loc = 0; loc < 4*4*MY_N1; loc++) {
         f_local[loc] = 0.0;
      }

      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k2]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k2];
      f_local[ind_1x+N1*0+N1*4*0] += c*my_F_2*ws01;
      f_local[ind_1y+N1*0+N1*4*0] += c*my_F_2*ws11;
      f_local[ind_1z+N1*0+N1*4*0] += c*my_F_2*ws21;
      f_local[ind_1w+N1*0+N1*4*0] += c*my_F_2*ws31;
      f_local[ind_1x+N1*1+N1*4*0] += c*my_F_2*ws41;
      f_local[ind_1y+N1*1+N1*4*0] += c*my_F_2*ws51;
      f_local[ind_1z+N1*1+N1*4*0] += c*my_F_2*ws61;
      f_local[ind_1w+N1*1+N1*4*0] += c*my_F_2*ws71;
      f_local[ind_1x+N1*2+N1*4*0] += c*my_F_2*ws81;
      f_local[ind_1y+N1*2+N1*4*0] += c*my_F_2*ws91;
      f_local[ind_1z+N1*2+N1*4*0] += c*my_F_2*wsa1;
      f_local[ind_1w+N1*2+N1*4*0] += c*my_F_2*wsb1;
      f_local[ind_1x+N1*3+N1*4*0] += c*my_F_2*wsc1;
      f_local[ind_1y+N1*3+N1*4*0] += c*my_F_2*wsd1;
      f_local[ind_1z+N1*3+N1*4*0] += c*my_F_2*wse1;
      f_local[ind_1w+N1*3+N1*4*0] += c*my_F_2*wsf1;

      f_local[ind_1x+N1*0+N1*4*1] += c*my_F_2*ws02;
      f_local[ind_1y+N1*0+N1*4*1] += c*my_F_2*ws12;
      f_local[ind_1z+N1*0+N1*4*1] += c*my_F_2*ws22;
      f_local[ind_1w+N1*0+N1*4*1] += c*my_F_2*ws32;
      f_local[ind_1x+N1*1+N1*4*1] += c*my_F_2*ws42;
      f_local[ind_1y+N1*1+N1*4*1] += c*my_F_2*ws52;
      f_local[ind_1z+N1*1+N1*4*1] += c*my_F_2*ws62;
      f_local[ind_1w+N1*1+N1*4*1] += c*my_F_2*ws72;
      f_local[ind_1x+N1*2+N1*4*1] += c*my_F_2*ws82;
      f_local[ind_1y+N1*2+N1*4*1] += c*my_F_2*ws92;
      f_local[ind_1z+N1*2+N1*4*1] += c*my_F_2*wsa2;
      f_local[ind_1w+N1*2+N1*4*1] += c*my_F_2*wsb2;
      f_local[ind_1x+N1*3+N1*4*1] += c*my_F_2*wsc2;
      f_local[ind_1y+N1*3+N1*4*1] += c*my_F_2*wsd2;
      f_local[ind_1z+N1*3+N1*4*1] += c*my_F_2*wse2;
      f_local[ind_1w+N1*3+N1*4*1] += c*my_F_2*wsf2;

      f_local[ind_1x+N1*0+N1*4*2] += c*my_F_2*ws03;
      f_local[ind_1y+N1*0+N1*4*2] += c*my_F_2*ws13;
      f_local[ind_1z+N1*0+N1*4*2] += c*my_F_2*ws23;
      f_local[ind_1w+N1*0+N1*4*2] += c*my_F_2*ws33;
      f_local[ind_1x+N1*1+N1*4*2] += c*my_F_2*ws43;
      f_local[ind_1y+N1*1+N1*4*2] += c*my_F_2*ws53;
      f_local[ind_1z+N1*1+N1*4*2] += c*my_F_2*ws63;
      f_local[ind_1w+N1*1+N1*4*2] += c*my_F_2*ws73;
      f_local[ind_1x+N1*2+N1*4*2] += c*my_F_2*ws83;
      f_local[ind_1y+N1*2+N1*4*2] += c*my_F_2*ws93;
      f_local[ind_1z+N1*2+N1*4*2] += c*my_F_2*wsa3;
      f_local[ind_1w+N1*2+N1*4*2] += c*my_F_2*wsb3;
      f_local[ind_1x+N1*3+N1*4*2] += c*my_F_2*wsc3;
      f_local[ind_1y+N1*3+N1*4*2] += c*my_F_2*wsd3;
      f_local[ind_1z+N1*3+N1*4*2] += c*my_F_2*wse3;
      f_local[ind_1w+N1*3+N1*4*2] += c*my_F_2*wsf3;

      f_local[ind_1x+N1*0+N1*4*3] += c*my_F_2*ws04;
      f_local[ind_1y+N1*0+N1*4*3] += c*my_F_2*ws14;
      f_local[ind_1z+N1*0+N1*4*3] += c*my_F_2*ws24;
      f_local[ind_1w+N1*0+N1*4*3] += c*my_F_2*ws34;
      f_local[ind_1x+N1*1+N1*4*3] += c*my_F_2*ws44;
      f_local[ind_1y+N1*1+N1*4*3] += c*my_F_2*ws54;
      f_local[ind_1z+N1*1+N1*4*3] += c*my_F_2*ws64;
      f_local[ind_1w+N1*1+N1*4*3] += c*my_F_2*ws74;
      f_local[ind_1x+N1*2+N1*4*3] += c*my_F_2*ws84;
      f_local[ind_1y+N1*2+N1*4*3] += c*my_F_2*ws94;
      f_local[ind_1z+N1*2+N1*4*3] += c*my_F_2*wsa4;
      f_local[ind_1w+N1*2+N1*4*3] += c*my_F_2*wsb4;
      f_local[ind_1x+N1*3+N1*4*3] += c*my_F_2*wsc4;
      f_local[ind_1y+N1*3+N1*4*3] += c*my_F_2*wsd4;
      f_local[ind_1z+N1*3+N1*4*3] += c*my_F_2*wse4;
      f_local[ind_1w+N1*3+N1*4*3] += c*my_F_2*wsf4;

      k2 = nextn2[k2];
      if (k2 == -1){
      for (unsigned kk = 0; kk<4; kk++) {
      for (unsigned jj = 0; jj<4; jj++) {
      for (unsigned ii = 0; ii<N1; ii++) {
         f_2[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]] = f_2[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]]+f_local[ii+N1*jj+N1*4*kk];
      }
      }
      }
      }
      }

      //f_local = {0.0};
      while(k3 != -1)
      {
      for (unsigned loc = 0; loc < 4*4*MY_N1; loc++) {
         f_local[loc] = 0.0;
      }

      float s_1_stag = (X_1[k3]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k3]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k3];
      f_local[ind_1x+N1*0+N1*4*0] += c*my_F_3*ws01;
      f_local[ind_1y+N1*0+N1*4*0] += c*my_F_3*ws11;
      f_local[ind_1z+N1*0+N1*4*0] += c*my_F_3*ws21;
      f_local[ind_1w+N1*0+N1*4*0] += c*my_F_3*ws31;
      f_local[ind_1x+N1*1+N1*4*0] += c*my_F_3*ws41;
      f_local[ind_1y+N1*1+N1*4*0] += c*my_F_3*ws51;
      f_local[ind_1z+N1*1+N1*4*0] += c*my_F_3*ws61;
      f_local[ind_1w+N1*1+N1*4*0] += c*my_F_3*ws71;
      f_local[ind_1x+N1*2+N1*4*0] += c*my_F_3*ws81;
      f_local[ind_1y+N1*2+N1*4*0] += c*my_F_3*ws91;
      f_local[ind_1z+N1*2+N1*4*0] += c*my_F_3*wsa1;
      f_local[ind_1w+N1*2+N1*4*0] += c*my_F_3*wsb1;
      f_local[ind_1x+N1*3+N1*4*0] += c*my_F_3*wsc1;
      f_local[ind_1y+N1*3+N1*4*0] += c*my_F_3*wsd1;
      f_local[ind_1z+N1*3+N1*4*0] += c*my_F_3*wse1;
      f_local[ind_1w+N1*3+N1*4*0] += c*my_F_3*wsf1;

      f_local[ind_1x+N1*0+N1*4*1] += c*my_F_3*ws02;
      f_local[ind_1y+N1*0+N1*4*1] += c*my_F_3*ws12;
      f_local[ind_1z+N1*0+N1*4*1] += c*my_F_3*ws22;
      f_local[ind_1w+N1*0+N1*4*1] += c*my_F_3*ws32;
      f_local[ind_1x+N1*1+N1*4*1] += c*my_F_3*ws42;
      f_local[ind_1y+N1*1+N1*4*1] += c*my_F_3*ws52;
      f_local[ind_1z+N1*1+N1*4*1] += c*my_F_3*ws62;
      f_local[ind_1w+N1*1+N1*4*1] += c*my_F_3*ws72;
      f_local[ind_1x+N1*2+N1*4*1] += c*my_F_3*ws82;
      f_local[ind_1y+N1*2+N1*4*1] += c*my_F_3*ws92;
      f_local[ind_1z+N1*2+N1*4*1] += c*my_F_3*wsa2;
      f_local[ind_1w+N1*2+N1*4*1] += c*my_F_3*wsb2;
      f_local[ind_1x+N1*3+N1*4*1] += c*my_F_3*wsc2;
      f_local[ind_1y+N1*3+N1*4*1] += c*my_F_3*wsd2;
      f_local[ind_1z+N1*3+N1*4*1] += c*my_F_3*wse2;
      f_local[ind_1w+N1*3+N1*4*1] += c*my_F_3*wsf2;

      f_local[ind_1x+N1*0+N1*4*2] += c*my_F_3*ws03;
      f_local[ind_1y+N1*0+N1*4*2] += c*my_F_3*ws13;
      f_local[ind_1z+N1*0+N1*4*2] += c*my_F_3*ws23;
      f_local[ind_1w+N1*0+N1*4*2] += c*my_F_3*ws33;
      f_local[ind_1x+N1*1+N1*4*2] += c*my_F_3*ws43;
      f_local[ind_1y+N1*1+N1*4*2] += c*my_F_3*ws53;
      f_local[ind_1z+N1*1+N1*4*2] += c*my_F_3*ws63;
      f_local[ind_1w+N1*1+N1*4*2] += c*my_F_3*ws73;
      f_local[ind_1x+N1*2+N1*4*2] += c*my_F_3*ws83;
      f_local[ind_1y+N1*2+N1*4*2] += c*my_F_3*ws93;
      f_local[ind_1z+N1*2+N1*4*2] += c*my_F_3*wsa3;
      f_local[ind_1w+N1*2+N1*4*2] += c*my_F_3*wsb3;
      f_local[ind_1x+N1*3+N1*4*2] += c*my_F_3*wsc3;
      f_local[ind_1y+N1*3+N1*4*2] += c*my_F_3*wsd3;
      f_local[ind_1z+N1*3+N1*4*2] += c*my_F_3*wse3;
      f_local[ind_1w+N1*3+N1*4*2] += c*my_F_3*wsf3;

      f_local[ind_1x+N1*0+N1*4*3] += c*my_F_3*ws04;
      f_local[ind_1y+N1*0+N1*4*3] += c*my_F_3*ws14;
      f_local[ind_1z+N1*0+N1*4*3] += c*my_F_3*ws24;
      f_local[ind_1w+N1*0+N1*4*3] += c*my_F_3*ws34;
      f_local[ind_1x+N1*1+N1*4*3] += c*my_F_3*ws44;
      f_local[ind_1y+N1*1+N1*4*3] += c*my_F_3*ws54;
      f_local[ind_1z+N1*1+N1*4*3] += c*my_F_3*ws64;
      f_local[ind_1w+N1*1+N1*4*3] += c*my_F_3*ws74;
      f_local[ind_1x+N1*2+N1*4*3] += c*my_F_3*ws84;
      f_local[ind_1y+N1*2+N1*4*3] += c*my_F_3*ws94;
      f_local[ind_1z+N1*2+N1*4*3] += c*my_F_3*wsa4;
      f_local[ind_1w+N1*2+N1*4*3] += c*my_F_3*wsb4;
      f_local[ind_1x+N1*3+N1*4*3] += c*my_F_3*wsc4;
      f_local[ind_1y+N1*3+N1*4*3] += c*my_F_3*wsd4;
      f_local[ind_1z+N1*3+N1*4*3] += c*my_F_3*wse4;
      f_local[ind_1w+N1*3+N1*4*3] += c*my_F_3*wsf4;

      k3 = nextn3[k3];
      if (k3 == -1){
      for (unsigned kk = 0; kk<4; kk++) {
      for (unsigned jj = 0; jj<4; jj++) {
      for (unsigned ii = 0; ii<N1; ii++) {
         f_3[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]] = f_3[ii+N1*ind_2[jj]+N1*N2*ind_3[kk]]+f_local[ii+N1*jj+N1*4*kk];
      }
      }
      }
      }
      }
    }
    __kernel void spread_simple_col(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, const unsigned shift0, const unsigned shift1, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      int k1 = firstn1[i+N2*j]; 
      int k2 = firstn2[i+N2*j]; 
      int k3 = firstn3[i+N2*j]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      ind_2x = (i-1 & N2-1);
      ind_2y = (i & N2-1);
      ind_2z = (i+1 & N2-1);
      ind_2w = (i+2 & N2-1);

      ind_3x = (j-1 & N3-1);
      ind_3y = (j & N3-1);
      ind_3z = (j+1 & N3-1);
      ind_3w = (j+2 & N3-1);

      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k1]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k1]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k1];
      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws01;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws11;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws21;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_1*ws31;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws41;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws51;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws61;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_1*ws71;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*ws81;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*ws91;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*wsa1;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_1*wsb1;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsc1;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsd1;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wse1;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_1*wsf1;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws02;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws12;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws22;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_1*ws32;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws42;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws52;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws62;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_1*ws72;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*ws82;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*ws92;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*wsa2;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_1*wsb2;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsc2;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsd2;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wse2;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_1*wsf2;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws03;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws13;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws23;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_1*ws33;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws43;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws53;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws63;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_1*ws73;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*ws83;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*ws93;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*wsa3;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_1*wsb3;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsc3;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsd3;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wse3;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_1*wsf3;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws04;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws14;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws24;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_1*ws34;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws44;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws54;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws64;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_1*ws74;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*ws84;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*ws94;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*wsa4;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_1*wsb4;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsc4;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsd4;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wse4;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_1*wsf4;

      k1 = nextn1[k1];
      }

      while(k2 != -1)
      {
      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k2]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k2];
      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws01;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws11;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws21;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_2*ws31;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws41;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws51;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws61;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_2*ws71;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*ws81;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*ws91;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*wsa1;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_2*wsb1;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsc1;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsd1;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wse1;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_2*wsf1;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws02;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws12;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws22;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_2*ws32;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws42;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws52;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws62;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_2*ws72;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*ws82;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*ws92;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*wsa2;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_2*wsb2;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsc2;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsd2;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wse2;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_2*wsf2;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws03;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws13;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws23;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_2*ws33;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws43;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws53;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws63;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_2*ws73;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*ws83;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*ws93;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*wsa3;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_2*wsb3;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsc3;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsd3;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wse3;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_2*wsf3;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws04;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws14;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws24;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_2*ws34;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws44;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws54;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws64;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_2*ws74;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*ws84;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*ws94;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*wsa4;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_2*wsb4;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsc4;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsd4;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wse4;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_2*wsf4;

      k2 = nextn2[k2];
      }

      while(k3 != -1)
      {
      float s_1_stag = (X_1[k3]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k3]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k3];
      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws01;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws11;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws21;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x] += c*my_F_3*ws31;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws41;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws51;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws61;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x] += c*my_F_3*ws71;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*ws81;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*ws91;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*wsa1;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x] += c*my_F_3*wsb1;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsc1;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsd1;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wse1;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x] += c*my_F_3*wsf1;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws02;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws12;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws22;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y] += c*my_F_3*ws32;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws42;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws52;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws62;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y] += c*my_F_3*ws72;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*ws82;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*ws92;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*wsa2;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y] += c*my_F_3*wsb2;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsc2;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsd2;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wse2;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y] += c*my_F_3*wsf2;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws03;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws13;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws23;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z] += c*my_F_3*ws33;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws43;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws53;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws63;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z] += c*my_F_3*ws73;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*ws83;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*ws93;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*wsa3;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z] += c*my_F_3*wsb3;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsc3;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsd3;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wse3;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z] += c*my_F_3*wsf3;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws04;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws14;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws24;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w] += c*my_F_3*ws34;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws44;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws54;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws64;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w] += c*my_F_3*ws74;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*ws84;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*ws94;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*wsa4;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w] += c*my_F_3*wsb4;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsc4;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsd4;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wse4;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w] += c*my_F_3*wsf4;

      k3 = nextn3[k3];
      }
    }
    __kernel void spread_pre_col(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = get_global_id(0);
      unsigned j = get_global_id(1);
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      int k1 = firstn1[i+N1*j]; 
      int k2 = firstn2[i+N1*j]; 
      int k3 = firstn3[i+N1*j]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      float c = dtheta/(dx1*dx2*dx3);

      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k1]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k1]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k1];
      f_1[0+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws01;
      f_1[1+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws11;
      f_1[2+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws21;
      f_1[3+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws31;
      f_1[0+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws41;
      f_1[1+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws51;
      f_1[2+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws61;
      f_1[3+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws71;
      f_1[0+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws81;
      f_1[1+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws91;
      f_1[2+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsa1;
      f_1[3+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsb1;
      f_1[0+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsc1;
      f_1[1+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsd1;
      f_1[2+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wse1;
      f_1[3+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsf1;

      f_1[0+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws02;
      f_1[1+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws12;
      f_1[2+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws22;
      f_1[3+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws32;
      f_1[0+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws42;
      f_1[1+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws52;
      f_1[2+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws62;
      f_1[3+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws72;
      f_1[0+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws82;
      f_1[1+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws92;
      f_1[2+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsa2;
      f_1[3+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsb2;
      f_1[0+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsc2;
      f_1[1+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsd2;
      f_1[2+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wse2;
      f_1[3+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsf2;

      f_1[0+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws03;
      f_1[1+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws13;
      f_1[2+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws23;
      f_1[3+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws33;
      f_1[0+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws43;
      f_1[1+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws53;
      f_1[2+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws63;
      f_1[3+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws73;
      f_1[0+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws83;
      f_1[1+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws93;
      f_1[2+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsa3;
      f_1[3+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsb3;
      f_1[0+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsc3;
      f_1[1+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsd3;
      f_1[2+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wse3;
      f_1[3+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsf3;

      f_1[0+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws04;
      f_1[1+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws14;
      f_1[2+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws24;
      f_1[3+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws34;
      f_1[0+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws44;
      f_1[1+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws54;
      f_1[2+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws64;
      f_1[3+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws74;
      f_1[0+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws84;
      f_1[1+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*ws94;
      f_1[2+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsa4;
      f_1[3+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsb4;
      f_1[0+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsc4;
      f_1[1+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsd4;
      f_1[2+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wse4;
      f_1[3+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F_1*wsf4;

      k1 = nextn1[k1];
      }

      while(k2 != -1)
      {
      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k2]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F = F_2[k2];
      f_2[0+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws01;
      f_2[1+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws11;
      f_2[2+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws21;
      f_2[3+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws31;
      f_2[0+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws41;
      f_2[1+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws51;
      f_2[2+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws61;
      f_2[3+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws71;
      f_2[0+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws81;
      f_2[1+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws91;
      f_2[2+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa1;
      f_2[3+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb1;
      f_2[0+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc1;
      f_2[1+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd1;
      f_2[2+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse1;
      f_2[3+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf1;

      f_2[0+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws02;
      f_2[1+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws12;
      f_2[2+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws22;
      f_2[3+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws32;
      f_2[0+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws42;
      f_2[1+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws52;
      f_2[2+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws62;
      f_2[3+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws72;
      f_2[0+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws82;
      f_2[1+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws92;
      f_2[2+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa2;
      f_2[3+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb2;
      f_2[0+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc2;
      f_2[1+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd2;
      f_2[2+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse2;
      f_2[3+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf2;

      f_2[0+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws03;
      f_2[1+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws13;
      f_2[2+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws23;
      f_2[3+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws33;
      f_2[0+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws43;
      f_2[1+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws53;
      f_2[2+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws63;
      f_2[3+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws73;
      f_2[0+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws83;
      f_2[1+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws93;
      f_2[2+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa3;
      f_2[3+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb3;
      f_2[0+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc3;
      f_2[1+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd3;
      f_2[2+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse3;
      f_2[3+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf3;

      f_2[0+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws04;
      f_2[1+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws14;
      f_2[2+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws24;
      f_2[3+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws34;
      f_2[0+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws44;
      f_2[1+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws54;
      f_2[2+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws64;
      f_2[3+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws74;
      f_2[0+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws84;
      f_2[1+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws94;
      f_2[2+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa4;
      f_2[3+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb4;
      f_2[0+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc4;
      f_2[1+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd4;
      f_2[2+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse4;
      f_2[3+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf4;

      k2 = nextn2[k2];
      }

      while(k3 != -1)
      {
      float s_1_stag = (X_1[k3]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k3]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      ind_3x = (i_3_stag-1 & N3-1);
      ind_3y = (i_3_stag & N3-1);
      ind_3z = (i_3_stag+1 & N3-1);
      ind_3w = (i_3_stag+2 & N3-1);

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F = F_3[k3];
      f_3[0+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws01;
      f_3[1+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws11;
      f_3[2+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws21;
      f_3[3+4*0+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws31;
      f_3[0+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws41;
      f_3[1+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws51;
      f_3[2+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws61;
      f_3[3+4*1+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws71;
      f_3[0+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws81;
      f_3[1+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws91;
      f_3[2+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa1;
      f_3[3+4*2+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb1;
      f_3[0+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc1;
      f_3[1+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd1;
      f_3[2+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse1;
      f_3[3+4*3+4*4*ind_3x+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf1;

      f_3[0+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws02;
      f_3[1+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws12;
      f_3[2+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws22;
      f_3[3+4*0+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws32;
      f_3[0+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws42;
      f_3[1+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws52;
      f_3[2+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws62;
      f_3[3+4*1+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws72;
      f_3[0+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws82;
      f_3[1+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws92;
      f_3[2+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa2;
      f_3[3+4*2+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb2;
      f_3[0+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc2;
      f_3[1+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd2;
      f_3[2+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse2;
      f_3[3+4*3+4*4*ind_3y+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf2;

      f_3[0+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws03;
      f_3[1+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws13;
      f_3[2+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws23;
      f_3[3+4*0+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws33;
      f_3[0+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws43;
      f_3[1+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws53;
      f_3[2+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws63;
      f_3[3+4*1+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws73;
      f_3[0+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws83;
      f_3[1+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws93;
      f_3[2+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa3;
      f_3[3+4*2+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb3;
      f_3[0+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc3;
      f_3[1+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd3;
      f_3[2+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse3;
      f_3[3+4*3+4*4*ind_3z+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf3;

      f_3[0+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws04;
      f_3[1+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws14;
      f_3[2+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws24;
      f_3[3+4*0+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws34;
      f_3[0+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws44;
      f_3[1+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws54;
      f_3[2+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws64;
      f_3[3+4*1+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws74;
      f_3[0+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws84;
      f_3[1+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*ws94;
      f_3[2+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsa4;
      f_3[3+4*2+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsb4;
      f_3[0+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsc4;
      f_3[1+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsd4;
      f_3[2+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wse4;
      f_3[3+4*3+4*4*ind_3w+4*4*N3*i+4*4*N3*N1*j] += c*my_F*wsf4;

      k3 = nextn3[k3];
      }
    }
    __kernel void spread(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const int *firstn3, __global const int *nextn3, __global const float *F_1, __global const float *F_2, __global const float *F_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float dtheta, const unsigned shift0, const unsigned shift1, const unsigned shift2, __global float *f_1, __global float *f_2, __global float *f_3)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      unsigned k = 4*get_global_id(2)+shift2;
      //k = 76;
      //j = 41;
      //i = 38;
      float L1 = dx1*N1;
      float L2 = dx2*N2;
      float L3 = dx3*N3;

      int k1 = firstn1[i+N1*j+N1*N2*k]; 
      int k2 = firstn2[i+N1*j+N1*N2*k]; 
      int k3 = firstn3[i+N1*j+N1*N2*k]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      float c = dtheta/(dx1*dx2*dx3);

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;

      float q1, q2, q3;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      float f_01, f_11, f_21, f_31;
      float f_41, f_51, f_61, f_71;
      float f_81, f_91, f_a1, f_b1;
      float f_c1, f_d1, f_e1, f_f1;

      float f_02, f_12, f_22, f_32;
      float f_42, f_52, f_62, f_72;
      float f_82, f_92, f_a2, f_b2;
      float f_c2, f_d2, f_e2, f_f2;

      float f_03, f_13, f_23, f_33;
      float f_43, f_53, f_63, f_73;
      float f_83, f_93, f_a3, f_b3;
      float f_c3, f_d3, f_e3, f_f3;

      float f_04, f_14, f_24, f_34;
      float f_44, f_54, f_64, f_74;
      float f_84, f_94, f_a4, f_b4;
      float f_c4, f_d4, f_e4, f_f4;

      if (k1 !=-1){
      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      f_01=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      f_11=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      f_21=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      f_31=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      f_41=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      f_51=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      f_61=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      f_71=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      f_81=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      f_91=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      f_a1=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      f_b1=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      f_c1=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      f_d1=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      f_e1=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      f_f1=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      f_02=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      f_12=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      f_22=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      f_32=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      f_42=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      f_52=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      f_62=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      f_72=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      f_82=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      f_92=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      f_a2=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      f_b2=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      f_c2=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      f_d2=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      f_e2=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      f_f2=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      f_03=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      f_13=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      f_23=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      f_33=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      f_43=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      f_53=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      f_63=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      f_73=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      f_83=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      f_93=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      f_a3=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      f_b3=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      f_c3=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      f_d3=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      f_e3=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      f_f3=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      f_04=f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      f_14=f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      f_24=f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      f_34=f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      f_44=f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      f_54=f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      f_64=f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      f_74=f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      f_84=f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      f_94=f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      f_a4=f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      f_b4=f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      f_c4=f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      f_d4=f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      f_e4=f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      f_f4=f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w];
      }
 
      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k1]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k1]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_1 = F_1[k1];
      f_01 += c*my_F_1*ws01;
      f_11 += c*my_F_1*ws11;
      f_21 += c*my_F_1*ws21;
      f_31 += c*my_F_1*ws31;
      f_41 += c*my_F_1*ws41;
      f_51 += c*my_F_1*ws51;
      f_61 += c*my_F_1*ws61;
      f_71 += c*my_F_1*ws71;
      f_81 += c*my_F_1*ws81;
      f_91 += c*my_F_1*ws91;
      f_a1 += c*my_F_1*wsa1;
      f_b1 += c*my_F_1*wsb1;
      f_c1 += c*my_F_1*wsc1;
      f_d1 += c*my_F_1*wsd1;
      f_e1 += c*my_F_1*wse1;
      f_f1 += c*my_F_1*wsf1;

      f_02 += c*my_F_1*ws02;
      f_12 += c*my_F_1*ws12;
      f_22 += c*my_F_1*ws22;
      f_32 += c*my_F_1*ws32;
      f_42 += c*my_F_1*ws42;
      f_52 += c*my_F_1*ws52;
      f_62 += c*my_F_1*ws62;
      f_72 += c*my_F_1*ws72;
      f_82 += c*my_F_1*ws82;
      f_92 += c*my_F_1*ws92;
      f_a2 += c*my_F_1*wsa2;
      f_b2 += c*my_F_1*wsb2;
      f_c2 += c*my_F_1*wsc2;
      f_d2 += c*my_F_1*wsd2;
      f_e2 += c*my_F_1*wse2;
      f_f2 += c*my_F_1*wsf2;

      f_03 += c*my_F_1*ws03;
      f_13 += c*my_F_1*ws13;
      f_23 += c*my_F_1*ws23;
      f_33 += c*my_F_1*ws33;
      f_43 += c*my_F_1*ws43;
      f_53 += c*my_F_1*ws53;
      f_63 += c*my_F_1*ws63;
      f_73 += c*my_F_1*ws73;
      f_83 += c*my_F_1*ws83;
      f_93 += c*my_F_1*ws93;
      f_a3 += c*my_F_1*wsa3;
      f_b3 += c*my_F_1*wsb3;
      f_c3 += c*my_F_1*wsc3;
      f_d3 += c*my_F_1*wsd3;
      f_e3 += c*my_F_1*wse3;
      f_f3 += c*my_F_1*wsf3;

      f_04 += c*my_F_1*ws04;
      f_14 += c*my_F_1*ws14;
      f_24 += c*my_F_1*ws24;
      f_34 += c*my_F_1*ws34;
      f_44 += c*my_F_1*ws44;
      f_54 += c*my_F_1*ws54;
      f_64 += c*my_F_1*ws64;
      f_74 += c*my_F_1*ws74;
      f_84 += c*my_F_1*ws84;
      f_94 += c*my_F_1*ws94;
      f_a4 += c*my_F_1*wsa4;
      f_b4 += c*my_F_1*wsb4;
      f_c4 += c*my_F_1*wsc4;
      f_d4 += c*my_F_1*wsd4;
      f_e4 += c*my_F_1*wse4;
      f_f4 += c*my_F_1*wsf4;

      k1 = nextn1[k1];
      if (k1 == -1){
      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3x]=f_01;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3x]=f_11;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3x]=f_21;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3x]=f_31;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3x]=f_41;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3x]=f_51;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3x]=f_61;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3x]=f_71;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3x]=f_81;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3x]=f_91;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3x]=f_a1;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3x]=f_b1;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3x]=f_c1;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3x]=f_d1;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3x]=f_e1;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3x]=f_f1;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3y]=f_02;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3y]=f_12;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3y]=f_22;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3y]=f_32;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3y]=f_42;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3y]=f_52;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3y]=f_62;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3y]=f_72;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3y]=f_82;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3y]=f_92;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3y]=f_a2;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3y]=f_b2;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3y]=f_c2;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3y]=f_d2;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3y]=f_e2;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3y]=f_f2;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3z]=f_03;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3z]=f_13;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3z]=f_23;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3z]=f_33;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3z]=f_43;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3z]=f_53;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3z]=f_63;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3z]=f_73;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3z]=f_83;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3z]=f_93;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3z]=f_a3;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3z]=f_b3;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3z]=f_c3;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3z]=f_d3;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3z]=f_e3;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3z]=f_f3;

      f_1[ind_1x+N1*ind_2x+N1*N2*ind_3w]=f_04;
      f_1[ind_1y+N1*ind_2x+N1*N2*ind_3w]=f_14;
      f_1[ind_1z+N1*ind_2x+N1*N2*ind_3w]=f_24;
      f_1[ind_1w+N1*ind_2x+N1*N2*ind_3w]=f_34;
      f_1[ind_1x+N1*ind_2y+N1*N2*ind_3w]=f_44;
      f_1[ind_1y+N1*ind_2y+N1*N2*ind_3w]=f_54;
      f_1[ind_1z+N1*ind_2y+N1*N2*ind_3w]=f_64;
      f_1[ind_1w+N1*ind_2y+N1*N2*ind_3w]=f_74;
      f_1[ind_1x+N1*ind_2z+N1*N2*ind_3w]=f_84;
      f_1[ind_1y+N1*ind_2z+N1*N2*ind_3w]=f_94;
      f_1[ind_1z+N1*ind_2z+N1*N2*ind_3w]=f_a4;
      f_1[ind_1w+N1*ind_2z+N1*N2*ind_3w]=f_b4;
      f_1[ind_1x+N1*ind_2w+N1*N2*ind_3w]=f_c4;
      f_1[ind_1y+N1*ind_2w+N1*N2*ind_3w]=f_d4;
      f_1[ind_1z+N1*ind_2w+N1*N2*ind_3w]=f_e4;
      f_1[ind_1w+N1*ind_2w+N1*N2*ind_3w]=f_f4;
      }
      }

      if (k2 !=-1){
      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      f_01=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      f_11=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      f_21=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      f_31=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      f_41=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      f_51=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      f_61=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      f_71=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      f_81=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      f_91=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      f_a1=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      f_b1=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      f_c1=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      f_d1=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      f_e1=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      f_f1=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      f_02=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      f_12=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      f_22=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      f_32=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      f_42=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      f_52=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      f_62=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      f_72=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      f_82=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      f_92=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      f_a2=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      f_b2=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      f_c2=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      f_d2=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      f_e2=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      f_f2=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      f_03=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      f_13=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      f_23=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      f_33=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      f_43=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      f_53=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      f_63=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      f_73=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      f_83=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      f_93=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      f_a3=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      f_b3=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      f_c3=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      f_d3=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      f_e3=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      f_f3=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      f_04=f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      f_14=f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      f_24=f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      f_34=f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      f_44=f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      f_54=f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      f_64=f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      f_74=f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      f_84=f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      f_94=f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      f_a4=f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      f_b4=f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      f_c4=f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      f_d4=f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      f_e4=f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      f_f4=f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w];
      }
 
      while(k2 != -1)
      {
      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k2]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_2 = F_2[k2];
      f_01 += c*my_F_2*ws01;
      f_11 += c*my_F_2*ws11;
      f_21 += c*my_F_2*ws21;
      f_31 += c*my_F_2*ws31;
      f_41 += c*my_F_2*ws41;
      f_51 += c*my_F_2*ws51;
      f_61 += c*my_F_2*ws61;
      f_71 += c*my_F_2*ws71;
      f_81 += c*my_F_2*ws81;
      f_91 += c*my_F_2*ws91;
      f_a1 += c*my_F_2*wsa1;
      f_b1 += c*my_F_2*wsb1;
      f_c1 += c*my_F_2*wsc1;
      f_d1 += c*my_F_2*wsd1;
      f_e1 += c*my_F_2*wse1;
      f_f1 += c*my_F_2*wsf1;

      f_02 += c*my_F_2*ws02;
      f_12 += c*my_F_2*ws12;
      f_22 += c*my_F_2*ws22;
      f_32 += c*my_F_2*ws32;
      f_42 += c*my_F_2*ws42;
      f_52 += c*my_F_2*ws52;
      f_62 += c*my_F_2*ws62;
      f_72 += c*my_F_2*ws72;
      f_82 += c*my_F_2*ws82;
      f_92 += c*my_F_2*ws92;
      f_a2 += c*my_F_2*wsa2;
      f_b2 += c*my_F_2*wsb2;
      f_c2 += c*my_F_2*wsc2;
      f_d2 += c*my_F_2*wsd2;
      f_e2 += c*my_F_2*wse2;
      f_f2 += c*my_F_2*wsf2;

      f_03 += c*my_F_2*ws03;
      f_13 += c*my_F_2*ws13;
      f_23 += c*my_F_2*ws23;
      f_33 += c*my_F_2*ws33;
      f_43 += c*my_F_2*ws43;
      f_53 += c*my_F_2*ws53;
      f_63 += c*my_F_2*ws63;
      f_73 += c*my_F_2*ws73;
      f_83 += c*my_F_2*ws83;
      f_93 += c*my_F_2*ws93;
      f_a3 += c*my_F_2*wsa3;
      f_b3 += c*my_F_2*wsb3;
      f_c3 += c*my_F_2*wsc3;
      f_d3 += c*my_F_2*wsd3;
      f_e3 += c*my_F_2*wse3;
      f_f3 += c*my_F_2*wsf3;

      f_04 += c*my_F_2*ws04;
      f_14 += c*my_F_2*ws14;
      f_24 += c*my_F_2*ws24;
      f_34 += c*my_F_2*ws34;
      f_44 += c*my_F_2*ws44;
      f_54 += c*my_F_2*ws54;
      f_64 += c*my_F_2*ws64;
      f_74 += c*my_F_2*ws74;
      f_84 += c*my_F_2*ws84;
      f_94 += c*my_F_2*ws94;
      f_a4 += c*my_F_2*wsa4;
      f_b4 += c*my_F_2*wsb4;
      f_c4 += c*my_F_2*wsc4;
      f_d4 += c*my_F_2*wsd4;
      f_e4 += c*my_F_2*wse4;
      f_f4 += c*my_F_2*wsf4;

      k2 = nextn2[k2];
      if (k2 == -1){
      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3x]=f_01;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3x]=f_11;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3x]=f_21;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3x]=f_31;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3x]=f_41;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3x]=f_51;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3x]=f_61;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3x]=f_71;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3x]=f_81;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3x]=f_91;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3x]=f_a1;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3x]=f_b1;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3x]=f_c1;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3x]=f_d1;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3x]=f_e1;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3x]=f_f1;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3y]=f_02;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3y]=f_12;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3y]=f_22;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3y]=f_32;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3y]=f_42;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3y]=f_52;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3y]=f_62;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3y]=f_72;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3y]=f_82;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3y]=f_92;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3y]=f_a2;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3y]=f_b2;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3y]=f_c2;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3y]=f_d2;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3y]=f_e2;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3y]=f_f2;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3z]=f_03;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3z]=f_13;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3z]=f_23;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3z]=f_33;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3z]=f_43;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3z]=f_53;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3z]=f_63;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3z]=f_73;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3z]=f_83;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3z]=f_93;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3z]=f_a3;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3z]=f_b3;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3z]=f_c3;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3z]=f_d3;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3z]=f_e3;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3z]=f_f3;

      f_2[ind_1x+N1*ind_2x+N1*N2*ind_3w]=f_04;
      f_2[ind_1y+N1*ind_2x+N1*N2*ind_3w]=f_14;
      f_2[ind_1z+N1*ind_2x+N1*N2*ind_3w]=f_24;
      f_2[ind_1w+N1*ind_2x+N1*N2*ind_3w]=f_34;
      f_2[ind_1x+N1*ind_2y+N1*N2*ind_3w]=f_44;
      f_2[ind_1y+N1*ind_2y+N1*N2*ind_3w]=f_54;
      f_2[ind_1z+N1*ind_2y+N1*N2*ind_3w]=f_64;
      f_2[ind_1w+N1*ind_2y+N1*N2*ind_3w]=f_74;
      f_2[ind_1x+N1*ind_2z+N1*N2*ind_3w]=f_84;
      f_2[ind_1y+N1*ind_2z+N1*N2*ind_3w]=f_94;
      f_2[ind_1z+N1*ind_2z+N1*N2*ind_3w]=f_a4;
      f_2[ind_1w+N1*ind_2z+N1*N2*ind_3w]=f_b4;
      f_2[ind_1x+N1*ind_2w+N1*N2*ind_3w]=f_c4;
      f_2[ind_1y+N1*ind_2w+N1*N2*ind_3w]=f_d4;
      f_2[ind_1z+N1*ind_2w+N1*N2*ind_3w]=f_e4;
      f_2[ind_1w+N1*ind_2w+N1*N2*ind_3w]=f_f4;
      }
      }

      if (k3 !=-1){
      ind_1x = (i-1 & N1-1);
      ind_1y = (i & N1-1);
      ind_1z = (i+1 & N1-1);
      ind_1w = (i+2 & N1-1);

      ind_2x = (j-1 & N2-1);
      ind_2y = (j & N2-1);
      ind_2z = (j+1 & N2-1);
      ind_2w = (j+2 & N2-1);

      ind_3x = (k-1 & N3-1);
      ind_3y = (k & N3-1);
      ind_3z = (k+1 & N3-1);
      ind_3w = (k+2 & N3-1);

      f_01=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      f_11=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      f_21=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      f_31=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      f_41=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      f_51=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      f_61=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      f_71=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      f_81=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      f_91=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      f_a1=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      f_b1=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      f_c1=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      f_d1=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      f_e1=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      f_f1=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      f_02=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      f_12=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      f_22=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      f_32=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      f_42=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      f_52=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      f_62=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      f_72=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      f_82=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      f_92=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      f_a2=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      f_b2=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      f_c2=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      f_d2=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      f_e2=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      f_f2=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      f_03=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      f_13=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      f_23=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      f_33=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      f_43=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      f_53=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      f_63=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      f_73=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      f_83=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      f_93=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      f_a3=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      f_b3=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      f_c3=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      f_d3=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      f_e3=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      f_f3=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      f_04=f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      f_14=f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      f_24=f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      f_34=f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      f_44=f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      f_54=f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      f_64=f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      f_74=f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      f_84=f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      f_94=f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      f_a4=f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      f_b4=f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      f_c4=f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      f_d4=f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      f_e4=f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      f_f4=f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w];
      }
 
      while(k3 != -1)
      {
      float s_1_stag = (X_1[k3]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2.0)/dx1;
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2.0)/dx2;        
      float s_3_c = (X_3[k3]+L3*0.5-dx3/2.0)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;
      
      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      float my_F_3 = F_3[k3];
      f_01 += c*my_F_3*ws01;
      f_11 += c*my_F_3*ws11;
      f_21 += c*my_F_3*ws21;
      f_31 += c*my_F_3*ws31;
      f_41 += c*my_F_3*ws41;
      f_51 += c*my_F_3*ws51;
      f_61 += c*my_F_3*ws61;
      f_71 += c*my_F_3*ws71;
      f_81 += c*my_F_3*ws81;
      f_91 += c*my_F_3*ws91;
      f_a1 += c*my_F_3*wsa1;
      f_b1 += c*my_F_3*wsb1;
      f_c1 += c*my_F_3*wsc1;
      f_d1 += c*my_F_3*wsd1;
      f_e1 += c*my_F_3*wse1;
      f_f1 += c*my_F_3*wsf1;

      f_02 += c*my_F_3*ws02;
      f_12 += c*my_F_3*ws12;
      f_22 += c*my_F_3*ws22;
      f_32 += c*my_F_3*ws32;
      f_42 += c*my_F_3*ws42;
      f_52 += c*my_F_3*ws52;
      f_62 += c*my_F_3*ws62;
      f_72 += c*my_F_3*ws72;
      f_82 += c*my_F_3*ws82;
      f_92 += c*my_F_3*ws92;
      f_a2 += c*my_F_3*wsa2;
      f_b2 += c*my_F_3*wsb2;
      f_c2 += c*my_F_3*wsc2;
      f_d2 += c*my_F_3*wsd2;
      f_e2 += c*my_F_3*wse2;
      f_f2 += c*my_F_3*wsf2;

      f_03 += c*my_F_3*ws03;
      f_13 += c*my_F_3*ws13;
      f_23 += c*my_F_3*ws23;
      f_33 += c*my_F_3*ws33;
      f_43 += c*my_F_3*ws43;
      f_53 += c*my_F_3*ws53;
      f_63 += c*my_F_3*ws63;
      f_73 += c*my_F_3*ws73;
      f_83 += c*my_F_3*ws83;
      f_93 += c*my_F_3*ws93;
      f_a3 += c*my_F_3*wsa3;
      f_b3 += c*my_F_3*wsb3;
      f_c3 += c*my_F_3*wsc3;
      f_d3 += c*my_F_3*wsd3;
      f_e3 += c*my_F_3*wse3;
      f_f3 += c*my_F_3*wsf3;

      f_04 += c*my_F_3*ws04;
      f_14 += c*my_F_3*ws14;
      f_24 += c*my_F_3*ws24;
      f_34 += c*my_F_3*ws34;
      f_44 += c*my_F_3*ws44;
      f_54 += c*my_F_3*ws54;
      f_64 += c*my_F_3*ws64;
      f_74 += c*my_F_3*ws74;
      f_84 += c*my_F_3*ws84;
      f_94 += c*my_F_3*ws94;
      f_a4 += c*my_F_3*wsa4;
      f_b4 += c*my_F_3*wsb4;
      f_c4 += c*my_F_3*wsc4;
      f_d4 += c*my_F_3*wsd4;
      f_e4 += c*my_F_3*wse4;
      f_f4 += c*my_F_3*wsf4;

      k3 = nextn3[k3];
      if (k3 == -1){
      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3x]=f_01;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3x]=f_11;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3x]=f_21;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3x]=f_31;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3x]=f_41;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3x]=f_51;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3x]=f_61;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3x]=f_71;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3x]=f_81;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3x]=f_91;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3x]=f_a1;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3x]=f_b1;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3x]=f_c1;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3x]=f_d1;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3x]=f_e1;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3x]=f_f1;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3y]=f_02;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3y]=f_12;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3y]=f_22;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3y]=f_32;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3y]=f_42;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3y]=f_52;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3y]=f_62;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3y]=f_72;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3y]=f_82;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3y]=f_92;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3y]=f_a2;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3y]=f_b2;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3y]=f_c2;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3y]=f_d2;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3y]=f_e2;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3y]=f_f2;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3z]=f_03;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3z]=f_13;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3z]=f_23;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3z]=f_33;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3z]=f_43;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3z]=f_53;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3z]=f_63;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3z]=f_73;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3z]=f_83;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3z]=f_93;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3z]=f_a3;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3z]=f_b3;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3z]=f_c3;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3z]=f_d3;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3z]=f_e3;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3z]=f_f3;

      f_3[ind_1x+N1*ind_2x+N1*N2*ind_3w]=f_04;
      f_3[ind_1y+N1*ind_2x+N1*N2*ind_3w]=f_14;
      f_3[ind_1z+N1*ind_2x+N1*N2*ind_3w]=f_24;
      f_3[ind_1w+N1*ind_2x+N1*N2*ind_3w]=f_34;
      f_3[ind_1x+N1*ind_2y+N1*N2*ind_3w]=f_44;
      f_3[ind_1y+N1*ind_2y+N1*N2*ind_3w]=f_54;
      f_3[ind_1z+N1*ind_2y+N1*N2*ind_3w]=f_64;
      f_3[ind_1w+N1*ind_2y+N1*N2*ind_3w]=f_74;
      f_3[ind_1x+N1*ind_2z+N1*N2*ind_3w]=f_84;
      f_3[ind_1y+N1*ind_2z+N1*N2*ind_3w]=f_94;
      f_3[ind_1z+N1*ind_2z+N1*N2*ind_3w]=f_a4;
      f_3[ind_1w+N1*ind_2z+N1*N2*ind_3w]=f_b4;
      f_3[ind_1x+N1*ind_2w+N1*N2*ind_3w]=f_c4;
      f_3[ind_1y+N1*ind_2w+N1*N2*ind_3w]=f_d4;
      f_3[ind_1z+N1*ind_2w+N1*N2*ind_3w]=f_e4;
      f_3[ind_1w+N1*ind_2w+N1*N2*ind_3w]=f_f4;
      }
      }
    }
    __kernel void interp(__global const float *u_1, __global const float *u_2, __global const float *u_3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, __global float *U_1, __global float *U_2, __global float *U_3)
    {
      unsigned k = get_global_id(0);
      float L1 = N1*dx1;
      float L2 = N2*dx2;
      float L3 = N3*dx3;
      float s_1_stag = (X_1[k]+L1*0.5)/dx1;
      float s_2_stag = (X_2[k]+L2*0.5)/dx2;       
      float s_3_stag = (X_3[k]+L3*0.5)/dx3;       
      int i_1_stag = convert_int(floor(s_1_stag));
      int i_2_stag = convert_int(floor(s_2_stag));
      int i_3_stag = convert_int(floor(s_3_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float r_2_stag = s_2_stag-i_2_stag;
      float r_3_stag = s_3_stag-i_3_stag;
      float s_1_c = (X_1[k]+L1*0.5-dx1/2)/dx1;
      float s_2_c = (X_2[k]+L2*0.5-dx2/2)/dx2;        
      float s_3_c = (X_3[k]+L3*0.5-dx3/2)/dx3;        
      int i_1_c = convert_int(floor(s_1_c));
      int i_2_c = convert_int(floor(s_2_c));
      int i_3_c = convert_int(floor(s_3_c));
      float r_1_c = s_1_c-i_1_c;
      float r_2_c = s_2_c-i_2_c;
      float r_3_c = s_3_c-i_3_c;

      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;
      int ind_3x, ind_3y, ind_3z, ind_3w;
      ind_1x = (i_1_stag-1 & N1-1);
      ind_1y = (i_1_stag & N1-1);
      ind_1z = (i_1_stag+1 & N1-1);
      ind_1w = (i_1_stag+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      float sb_tests01, sb_tests11, sb_tests21, sb_tests31;
      float sb_tests41, sb_tests51, sb_tests61, sb_tests71;
      float sb_tests81, sb_tests91, sb_testsa1, sb_testsb1;
      float sb_testsc1, sb_testsd1, sb_testse1, sb_testsf1;

      float sb_tests02, sb_tests12, sb_tests22, sb_tests32;
      float sb_tests42, sb_tests52, sb_tests62, sb_tests72;
      float sb_tests82, sb_tests92, sb_testsa2, sb_testsb2;
      float sb_testsc2, sb_testsd2, sb_testse2, sb_testsf2;

      float sb_tests03, sb_tests13, sb_tests23, sb_tests33;
      float sb_tests43, sb_tests53, sb_tests63, sb_tests73;
      float sb_tests83, sb_tests93, sb_testsa3, sb_testsb3;
      float sb_testsc3, sb_testsd3, sb_testse3, sb_testsf3;

      float sb_tests04, sb_tests14, sb_tests24, sb_tests34;
      float sb_tests44, sb_tests54, sb_tests64, sb_tests74;
      float sb_tests84, sb_tests94, sb_testsa4, sb_testsb4;
      float sb_testsc4, sb_testsd4, sb_testse4, sb_testsf4;

      sb_tests01 = u_1[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      sb_tests11 = u_1[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      sb_tests21 = u_1[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      sb_tests31 = u_1[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      sb_tests41 = u_1[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      sb_tests51 = u_1[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      sb_tests61 = u_1[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      sb_tests71 = u_1[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      sb_tests81 = u_1[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      sb_tests91 = u_1[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      sb_testsa1 = u_1[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      sb_testsb1 = u_1[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      sb_testsc1 = u_1[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      sb_testsd1 = u_1[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      sb_testse1 = u_1[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      sb_testsf1 = u_1[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      sb_tests02 = u_1[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      sb_tests12 = u_1[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      sb_tests22 = u_1[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      sb_tests32 = u_1[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      sb_tests42 = u_1[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      sb_tests52 = u_1[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      sb_tests62 = u_1[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      sb_tests72 = u_1[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      sb_tests82 = u_1[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      sb_tests92 = u_1[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      sb_testsa2 = u_1[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      sb_testsb2 = u_1[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      sb_testsc2 = u_1[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      sb_testsd2 = u_1[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      sb_testse2 = u_1[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      sb_testsf2 = u_1[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      sb_tests03 = u_1[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      sb_tests13 = u_1[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      sb_tests23 = u_1[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      sb_tests33 = u_1[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      sb_tests43 = u_1[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      sb_tests53 = u_1[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      sb_tests63 = u_1[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      sb_tests73 = u_1[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      sb_tests83 = u_1[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      sb_tests93 = u_1[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      sb_testsa3 = u_1[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      sb_testsb3 = u_1[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      sb_testsc3 = u_1[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      sb_testsd3 = u_1[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      sb_testse3 = u_1[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      sb_testsf3 = u_1[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      sb_tests04 = u_1[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      sb_tests14 = u_1[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      sb_tests24 = u_1[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      sb_tests34 = u_1[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      sb_tests44 = u_1[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      sb_tests54 = u_1[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      sb_tests64 = u_1[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      sb_tests74 = u_1[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      sb_tests84 = u_1[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      sb_tests94 = u_1[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      sb_testsa4 = u_1[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      sb_testsb4 = u_1[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      sb_testsc4 = u_1[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      sb_testsd4 = u_1[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      sb_testse4 = u_1[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      sb_testsf4 = u_1[ind_1w+N1*ind_2w+N1*N2*ind_3w];

      float q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      float q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      float q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;
      float v3x, v3y, v3z, v3w;

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      float ws01, ws11, ws21, ws31;
      float ws41, ws51, ws61, ws71;
      float ws81, ws91, wsa1, wsb1;
      float wsc1, wsd1, wse1, wsf1;

      float ws02, ws12, ws22, ws32;
      float ws42, ws52, ws62, ws72;
      float ws82, ws92, wsa2, wsb2;
      float wsc2, wsd2, wse2, wsf2;

      float ws03, ws13, ws23, ws33;
      float ws43, ws53, ws63, ws73;
      float ws83, ws93, wsa3, wsb3;
      float wsc3, wsd3, wse3, wsf3;

      float ws04, ws14, ws24, ws34;
      float ws44, ws54, ws64, ws74;
      float ws84, ws94, wsa4, wsb4;
      float wsc4, wsd4, wse4, wsf4;

      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      ws01 = ws01*sb_tests01;
      ws11 = ws11*sb_tests11;
      ws21 = ws21*sb_tests21;
      ws31 = ws31*sb_tests31;
      ws41 = ws41*sb_tests41;
      ws51 = ws51*sb_tests51;
      ws61 = ws61*sb_tests61;
      ws71 = ws71*sb_tests71;
      ws81 = ws81*sb_tests81;
      ws91 = ws91*sb_tests91;
      wsa1 = wsa1*sb_testsa1;
      wsb1 = wsb1*sb_testsb1;
      wsc1 = wsc1*sb_testsc1;
      wsd1 = wsd1*sb_testsd1;
      wse1 = wse1*sb_testse1;
      wsf1 = wsf1*sb_testsf1;

      ws02 = ws02*sb_tests02;
      ws12 = ws12*sb_tests12;
      ws22 = ws22*sb_tests22;
      ws32 = ws32*sb_tests32;
      ws42 = ws42*sb_tests42;
      ws52 = ws52*sb_tests52;
      ws62 = ws62*sb_tests62;
      ws72 = ws72*sb_tests72;
      ws82 = ws82*sb_tests82;
      ws92 = ws92*sb_tests92;
      wsa2 = wsa2*sb_testsa2;
      wsb2 = wsb2*sb_testsb2;
      wsc2 = wsc2*sb_testsc2;
      wsd2 = wsd2*sb_testsd2;
      wse2 = wse2*sb_testse2;
      wsf2 = wsf2*sb_testsf2;

      ws03 = ws03*sb_tests03;
      ws13 = ws13*sb_tests13;
      ws23 = ws23*sb_tests23;
      ws33 = ws33*sb_tests33;
      ws43 = ws43*sb_tests43;
      ws53 = ws53*sb_tests53;
      ws63 = ws63*sb_tests63;
      ws73 = ws73*sb_tests73;
      ws83 = ws83*sb_tests83;
      ws93 = ws93*sb_tests93;
      wsa3 = wsa3*sb_testsa3;
      wsb3 = wsb3*sb_testsb3;
      wsc3 = wsc3*sb_testsc3;
      wsd3 = wsd3*sb_testsd3;
      wse3 = wse3*sb_testse3;
      wsf3 = wsf3*sb_testsf3;

      ws04 = ws04*sb_tests04;
      ws14 = ws14*sb_tests14;
      ws24 = ws24*sb_tests24;
      ws34 = ws34*sb_tests34;
      ws44 = ws44*sb_tests44;
      ws54 = ws54*sb_tests54;
      ws64 = ws64*sb_tests64;
      ws74 = ws74*sb_tests74;
      ws84 = ws84*sb_tests84;
      ws94 = ws94*sb_tests94;
      wsa4 = wsa4*sb_testsa4;
      wsb4 = wsb4*sb_testsb4;
      wsc4 = wsc4*sb_testsc4;
      wsd4 = wsd4*sb_testsd4;
      wse4 = wse4*sb_testse4;
      wsf4 = wsf4*sb_testsf4;

      U_1[k] = ws01+ws11+ws21+ws31
	       +ws41+ws51+ws61+ws71
	       +ws81+ws91+wsa1+wsb1
	       +wsc1+wsd1+wse1+wsf1
               +ws02+ws12+ws22+ws32
	       +ws42+ws52+ws62+ws72
	       +ws82+ws92+wsa2+wsb2
	       +wsc2+wsd2+wse2+wsf2
               +ws03+ws13+ws23+ws33
	       +ws43+ws53+ws63+ws73
	       +ws83+ws93+wsa3+wsb3
	       +wsc3+wsd3+wse3+wsf3
               +ws04+ws14+ws24+ws34
	       +ws44+ws54+ws64+ws74
	       +ws84+ws94+wsa4+wsb4
	       +wsc4+wsd4+wse4+wsf4;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_stag-1 & N2-1);
      ind_2y = (i_2_stag & N2-1);
      ind_2z = (i_2_stag+1 & N2-1);
      ind_2w = (i_2_stag+2 & N2-1);

      ind_3x = (i_3_c-1 & N3-1);
      ind_3y = (i_3_c & N3-1);
      ind_3z = (i_3_c+1 & N3-1);
      ind_3w = (i_3_c+2 & N3-1);

      sb_tests01 = u_2[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      sb_tests11 = u_2[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      sb_tests21 = u_2[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      sb_tests31 = u_2[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      sb_tests41 = u_2[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      sb_tests51 = u_2[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      sb_tests61 = u_2[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      sb_tests71 = u_2[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      sb_tests81 = u_2[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      sb_tests91 = u_2[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      sb_testsa1 = u_2[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      sb_testsb1 = u_2[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      sb_testsc1 = u_2[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      sb_testsd1 = u_2[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      sb_testse1 = u_2[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      sb_testsf1 = u_2[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      sb_tests02 = u_2[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      sb_tests12 = u_2[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      sb_tests22 = u_2[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      sb_tests32 = u_2[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      sb_tests42 = u_2[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      sb_tests52 = u_2[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      sb_tests62 = u_2[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      sb_tests72 = u_2[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      sb_tests82 = u_2[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      sb_tests92 = u_2[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      sb_testsa2 = u_2[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      sb_testsb2 = u_2[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      sb_testsc2 = u_2[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      sb_testsd2 = u_2[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      sb_testse2 = u_2[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      sb_testsf2 = u_2[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      sb_tests03 = u_2[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      sb_tests13 = u_2[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      sb_tests23 = u_2[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      sb_tests33 = u_2[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      sb_tests43 = u_2[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      sb_tests53 = u_2[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      sb_tests63 = u_2[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      sb_tests73 = u_2[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      sb_tests83 = u_2[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      sb_tests93 = u_2[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      sb_testsa3 = u_2[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      sb_testsb3 = u_2[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      sb_testsc3 = u_2[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      sb_testsd3 = u_2[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      sb_testse3 = u_2[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      sb_testsf3 = u_2[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      sb_tests04 = u_2[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      sb_tests14 = u_2[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      sb_tests24 = u_2[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      sb_tests34 = u_2[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      sb_tests44 = u_2[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      sb_tests54 = u_2[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      sb_tests64 = u_2[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      sb_tests74 = u_2[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      sb_tests84 = u_2[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      sb_tests94 = u_2[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      sb_testsa4 = u_2[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      sb_testsb4 = u_2[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      sb_testsc4 = u_2[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      sb_testsd4 = u_2[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      sb_testse4 = u_2[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      sb_testsf4 = u_2[ind_1w+N1*ind_2w+N1*N2*ind_3w];

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));
      q3 = sqrt(1.+4.0*r_3_c*(1-r_3_c));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_c-q3; 
      v3y = 3.-2.*r_3_c+q3; 
      v3z = 1.+2.*r_3_c+q3; 
      v3w = 1.+2.*r_3_c-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      ws01 = ws01*sb_tests01;
      ws11 = ws11*sb_tests11;
      ws21 = ws21*sb_tests21;
      ws31 = ws31*sb_tests31;
      ws41 = ws41*sb_tests41;
      ws51 = ws51*sb_tests51;
      ws61 = ws61*sb_tests61;
      ws71 = ws71*sb_tests71;
      ws81 = ws81*sb_tests81;
      ws91 = ws91*sb_tests91;
      wsa1 = wsa1*sb_testsa1;
      wsb1 = wsb1*sb_testsb1;
      wsc1 = wsc1*sb_testsc1;
      wsd1 = wsd1*sb_testsd1;
      wse1 = wse1*sb_testse1;
      wsf1 = wsf1*sb_testsf1;

      ws02 = ws02*sb_tests02;
      ws12 = ws12*sb_tests12;
      ws22 = ws22*sb_tests22;
      ws32 = ws32*sb_tests32;
      ws42 = ws42*sb_tests42;
      ws52 = ws52*sb_tests52;
      ws62 = ws62*sb_tests62;
      ws72 = ws72*sb_tests72;
      ws82 = ws82*sb_tests82;
      ws92 = ws92*sb_tests92;
      wsa2 = wsa2*sb_testsa2;
      wsb2 = wsb2*sb_testsb2;
      wsc2 = wsc2*sb_testsc2;
      wsd2 = wsd2*sb_testsd2;
      wse2 = wse2*sb_testse2;
      wsf2 = wsf2*sb_testsf2;

      ws03 = ws03*sb_tests03;
      ws13 = ws13*sb_tests13;
      ws23 = ws23*sb_tests23;
      ws33 = ws33*sb_tests33;
      ws43 = ws43*sb_tests43;
      ws53 = ws53*sb_tests53;
      ws63 = ws63*sb_tests63;
      ws73 = ws73*sb_tests73;
      ws83 = ws83*sb_tests83;
      ws93 = ws93*sb_tests93;
      wsa3 = wsa3*sb_testsa3;
      wsb3 = wsb3*sb_testsb3;
      wsc3 = wsc3*sb_testsc3;
      wsd3 = wsd3*sb_testsd3;
      wse3 = wse3*sb_testse3;
      wsf3 = wsf3*sb_testsf3;

      ws04 = ws04*sb_tests04;
      ws14 = ws14*sb_tests14;
      ws24 = ws24*sb_tests24;
      ws34 = ws34*sb_tests34;
      ws44 = ws44*sb_tests44;
      ws54 = ws54*sb_tests54;
      ws64 = ws64*sb_tests64;
      ws74 = ws74*sb_tests74;
      ws84 = ws84*sb_tests84;
      ws94 = ws94*sb_tests94;
      wsa4 = wsa4*sb_testsa4;
      wsb4 = wsb4*sb_testsb4;
      wsc4 = wsc4*sb_testsc4;
      wsd4 = wsd4*sb_testsd4;
      wse4 = wse4*sb_testse4;
      wsf4 = wsf4*sb_testsf4;

      U_2[k] = ws01+ws11+ws21+ws31
	       +ws41+ws51+ws61+ws71
	       +ws81+ws91+wsa1+wsb1
	       +wsc1+wsd1+wse1+wsf1
               +ws02+ws12+ws22+ws32
	       +ws42+ws52+ws62+ws72
	       +ws82+ws92+wsa2+wsb2
	       +wsc2+wsd2+wse2+wsf2
               +ws03+ws13+ws23+ws33
	       +ws43+ws53+ws63+ws73
	       +ws83+ws93+wsa3+wsb3
	       +wsc3+wsd3+wse3+wsf3
               +ws04+ws14+ws24+ws34
	       +ws44+ws54+ws64+ws74
	       +ws84+ws94+wsa4+wsb4
	       +wsc4+wsd4+wse4+wsf4;

      ind_1x = (i_1_c-1 & N1-1);
      ind_1y = (i_1_c & N1-1);
      ind_1z = (i_1_c+1 & N1-1);
      ind_1w = (i_1_c+2 & N1-1);

      ind_2x = (i_2_c-1 & N2-1);
      ind_2y = (i_2_c & N2-1);
      ind_2z = (i_2_c+1 & N2-1);
      ind_2w = (i_2_c+2 & N2-1);

      ind_3x = (i_3_stag-1 & N3-1);
      ind_3y = (i_3_stag & N3-1);
      ind_3z = (i_3_stag+1 & N3-1);
      ind_3w = (i_3_stag+2 & N3-1);

      sb_tests01 = u_3[ind_1x+N1*ind_2x+N1*N2*ind_3x];
      sb_tests11 = u_3[ind_1y+N1*ind_2x+N1*N2*ind_3x];
      sb_tests21 = u_3[ind_1z+N1*ind_2x+N1*N2*ind_3x];
      sb_tests31 = u_3[ind_1w+N1*ind_2x+N1*N2*ind_3x];
      sb_tests41 = u_3[ind_1x+N1*ind_2y+N1*N2*ind_3x];
      sb_tests51 = u_3[ind_1y+N1*ind_2y+N1*N2*ind_3x];
      sb_tests61 = u_3[ind_1z+N1*ind_2y+N1*N2*ind_3x];
      sb_tests71 = u_3[ind_1w+N1*ind_2y+N1*N2*ind_3x];
      sb_tests81 = u_3[ind_1x+N1*ind_2z+N1*N2*ind_3x];
      sb_tests91 = u_3[ind_1y+N1*ind_2z+N1*N2*ind_3x];
      sb_testsa1 = u_3[ind_1z+N1*ind_2z+N1*N2*ind_3x];
      sb_testsb1 = u_3[ind_1w+N1*ind_2z+N1*N2*ind_3x];
      sb_testsc1 = u_3[ind_1x+N1*ind_2w+N1*N2*ind_3x];
      sb_testsd1 = u_3[ind_1y+N1*ind_2w+N1*N2*ind_3x];
      sb_testse1 = u_3[ind_1z+N1*ind_2w+N1*N2*ind_3x];
      sb_testsf1 = u_3[ind_1w+N1*ind_2w+N1*N2*ind_3x];

      sb_tests02 = u_3[ind_1x+N1*ind_2x+N1*N2*ind_3y];
      sb_tests12 = u_3[ind_1y+N1*ind_2x+N1*N2*ind_3y];
      sb_tests22 = u_3[ind_1z+N1*ind_2x+N1*N2*ind_3y];
      sb_tests32 = u_3[ind_1w+N1*ind_2x+N1*N2*ind_3y];
      sb_tests42 = u_3[ind_1x+N1*ind_2y+N1*N2*ind_3y];
      sb_tests52 = u_3[ind_1y+N1*ind_2y+N1*N2*ind_3y];
      sb_tests62 = u_3[ind_1z+N1*ind_2y+N1*N2*ind_3y];
      sb_tests72 = u_3[ind_1w+N1*ind_2y+N1*N2*ind_3y];
      sb_tests82 = u_3[ind_1x+N1*ind_2z+N1*N2*ind_3y];
      sb_tests92 = u_3[ind_1y+N1*ind_2z+N1*N2*ind_3y];
      sb_testsa2 = u_3[ind_1z+N1*ind_2z+N1*N2*ind_3y];
      sb_testsb2 = u_3[ind_1w+N1*ind_2z+N1*N2*ind_3y];
      sb_testsc2 = u_3[ind_1x+N1*ind_2w+N1*N2*ind_3y];
      sb_testsd2 = u_3[ind_1y+N1*ind_2w+N1*N2*ind_3y];
      sb_testse2 = u_3[ind_1z+N1*ind_2w+N1*N2*ind_3y];
      sb_testsf2 = u_3[ind_1w+N1*ind_2w+N1*N2*ind_3y];

      sb_tests03 = u_3[ind_1x+N1*ind_2x+N1*N2*ind_3z];
      sb_tests13 = u_3[ind_1y+N1*ind_2x+N1*N2*ind_3z];
      sb_tests23 = u_3[ind_1z+N1*ind_2x+N1*N2*ind_3z];
      sb_tests33 = u_3[ind_1w+N1*ind_2x+N1*N2*ind_3z];
      sb_tests43 = u_3[ind_1x+N1*ind_2y+N1*N2*ind_3z];
      sb_tests53 = u_3[ind_1y+N1*ind_2y+N1*N2*ind_3z];
      sb_tests63 = u_3[ind_1z+N1*ind_2y+N1*N2*ind_3z];
      sb_tests73 = u_3[ind_1w+N1*ind_2y+N1*N2*ind_3z];
      sb_tests83 = u_3[ind_1x+N1*ind_2z+N1*N2*ind_3z];
      sb_tests93 = u_3[ind_1y+N1*ind_2z+N1*N2*ind_3z];
      sb_testsa3 = u_3[ind_1z+N1*ind_2z+N1*N2*ind_3z];
      sb_testsb3 = u_3[ind_1w+N1*ind_2z+N1*N2*ind_3z];
      sb_testsc3 = u_3[ind_1x+N1*ind_2w+N1*N2*ind_3z];
      sb_testsd3 = u_3[ind_1y+N1*ind_2w+N1*N2*ind_3z];
      sb_testse3 = u_3[ind_1z+N1*ind_2w+N1*N2*ind_3z];
      sb_testsf3 = u_3[ind_1w+N1*ind_2w+N1*N2*ind_3z];

      sb_tests04 = u_3[ind_1x+N1*ind_2x+N1*N2*ind_3w];
      sb_tests14 = u_3[ind_1y+N1*ind_2x+N1*N2*ind_3w];
      sb_tests24 = u_3[ind_1z+N1*ind_2x+N1*N2*ind_3w];
      sb_tests34 = u_3[ind_1w+N1*ind_2x+N1*N2*ind_3w];
      sb_tests44 = u_3[ind_1x+N1*ind_2y+N1*N2*ind_3w];
      sb_tests54 = u_3[ind_1y+N1*ind_2y+N1*N2*ind_3w];
      sb_tests64 = u_3[ind_1z+N1*ind_2y+N1*N2*ind_3w];
      sb_tests74 = u_3[ind_1w+N1*ind_2y+N1*N2*ind_3w];
      sb_tests84 = u_3[ind_1x+N1*ind_2z+N1*N2*ind_3w];
      sb_tests94 = u_3[ind_1y+N1*ind_2z+N1*N2*ind_3w];
      sb_testsa4 = u_3[ind_1z+N1*ind_2z+N1*N2*ind_3w];
      sb_testsb4 = u_3[ind_1w+N1*ind_2z+N1*N2*ind_3w];
      sb_testsc4 = u_3[ind_1x+N1*ind_2w+N1*N2*ind_3w];
      sb_testsd4 = u_3[ind_1y+N1*ind_2w+N1*N2*ind_3w];
      sb_testse4 = u_3[ind_1z+N1*ind_2w+N1*N2*ind_3w];
      sb_testsf4 = u_3[ind_1w+N1*ind_2w+N1*N2*ind_3w];

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));
      q3 = sqrt(1.+4.0*r_3_stag*(1-r_3_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;

      v3x = 3.-2.*r_3_stag-q3; 
      v3y = 3.-2.*r_3_stag+q3; 
      v3z = 1.+2.*r_3_stag+q3; 
      v3w = 1.+2.*r_3_stag-q3; 
      v3x = v3x/8.;
      v3y = v3y/8.;
      v3z = v3z/8.;
      v3w = v3w/8.;
      
      ws01 = v1x*v2x*v3x;
      ws11 = v1y*v2x*v3x;
      ws21 = v1z*v2x*v3x;
      ws31 = v1w*v2x*v3x;
      ws41 = v1x*v2y*v3x;
      ws51 = v1y*v2y*v3x;
      ws61 = v1z*v2y*v3x;
      ws71 = v1w*v2y*v3x;
      ws81 = v1x*v2z*v3x;
      ws91 = v1y*v2z*v3x;
      wsa1 = v1z*v2z*v3x;
      wsb1 = v1w*v2z*v3x;
      wsc1 = v1x*v2w*v3x;
      wsd1 = v1y*v2w*v3x;
      wse1 = v1z*v2w*v3x;
      wsf1 = v1w*v2w*v3x;
      
      ws02 = v1x*v2x*v3y;
      ws12 = v1y*v2x*v3y;
      ws22 = v1z*v2x*v3y;
      ws32 = v1w*v2x*v3y;
      ws42 = v1x*v2y*v3y;
      ws52 = v1y*v2y*v3y;
      ws62 = v1z*v2y*v3y;
      ws72 = v1w*v2y*v3y;
      ws82 = v1x*v2z*v3y;
      ws92 = v1y*v2z*v3y;
      wsa2 = v1z*v2z*v3y;
      wsb2 = v1w*v2z*v3y;
      wsc2 = v1x*v2w*v3y;
      wsd2 = v1y*v2w*v3y;
      wse2 = v1z*v2w*v3y;
      wsf2 = v1w*v2w*v3y;

      ws03 = v1x*v2x*v3z;
      ws13 = v1y*v2x*v3z;
      ws23 = v1z*v2x*v3z;
      ws33 = v1w*v2x*v3z;
      ws43 = v1x*v2y*v3z;
      ws53 = v1y*v2y*v3z;
      ws63 = v1z*v2y*v3z;
      ws73 = v1w*v2y*v3z;
      ws83 = v1x*v2z*v3z;
      ws93 = v1y*v2z*v3z;
      wsa3 = v1z*v2z*v3z;
      wsb3 = v1w*v2z*v3z;
      wsc3 = v1x*v2w*v3z;
      wsd3 = v1y*v2w*v3z;
      wse3 = v1z*v2w*v3z;
      wsf3 = v1w*v2w*v3z;

      ws04 = v1x*v2x*v3w;
      ws14 = v1y*v2x*v3w;
      ws24 = v1z*v2x*v3w;
      ws34 = v1w*v2x*v3w;
      ws44 = v1x*v2y*v3w;
      ws54 = v1y*v2y*v3w;
      ws64 = v1z*v2y*v3w;
      ws74 = v1w*v2y*v3w;
      ws84 = v1x*v2z*v3w;
      ws94 = v1y*v2z*v3w;
      wsa4 = v1z*v2z*v3w;
      wsb4 = v1w*v2z*v3w;
      wsc4 = v1x*v2w*v3w;
      wsd4 = v1y*v2w*v3w;
      wse4 = v1z*v2w*v3w;
      wsf4 = v1w*v2w*v3w;

      ws01 = ws01*sb_tests01;
      ws11 = ws11*sb_tests11;
      ws21 = ws21*sb_tests21;
      ws31 = ws31*sb_tests31;
      ws41 = ws41*sb_tests41;
      ws51 = ws51*sb_tests51;
      ws61 = ws61*sb_tests61;
      ws71 = ws71*sb_tests71;
      ws81 = ws81*sb_tests81;
      ws91 = ws91*sb_tests91;
      wsa1 = wsa1*sb_testsa1;
      wsb1 = wsb1*sb_testsb1;
      wsc1 = wsc1*sb_testsc1;
      wsd1 = wsd1*sb_testsd1;
      wse1 = wse1*sb_testse1;
      wsf1 = wsf1*sb_testsf1;

      ws02 = ws02*sb_tests02;
      ws12 = ws12*sb_tests12;
      ws22 = ws22*sb_tests22;
      ws32 = ws32*sb_tests32;
      ws42 = ws42*sb_tests42;
      ws52 = ws52*sb_tests52;
      ws62 = ws62*sb_tests62;
      ws72 = ws72*sb_tests72;
      ws82 = ws82*sb_tests82;
      ws92 = ws92*sb_tests92;
      wsa2 = wsa2*sb_testsa2;
      wsb2 = wsb2*sb_testsb2;
      wsc2 = wsc2*sb_testsc2;
      wsd2 = wsd2*sb_testsd2;
      wse2 = wse2*sb_testse2;
      wsf2 = wsf2*sb_testsf2;

      ws03 = ws03*sb_tests03;
      ws13 = ws13*sb_tests13;
      ws23 = ws23*sb_tests23;
      ws33 = ws33*sb_tests33;
      ws43 = ws43*sb_tests43;
      ws53 = ws53*sb_tests53;
      ws63 = ws63*sb_tests63;
      ws73 = ws73*sb_tests73;
      ws83 = ws83*sb_tests83;
      ws93 = ws93*sb_tests93;
      wsa3 = wsa3*sb_testsa3;
      wsb3 = wsb3*sb_testsb3;
      wsc3 = wsc3*sb_testsc3;
      wsd3 = wsd3*sb_testsd3;
      wse3 = wse3*sb_testse3;
      wsf3 = wsf3*sb_testsf3;

      ws04 = ws04*sb_tests04;
      ws14 = ws14*sb_tests14;
      ws24 = ws24*sb_tests24;
      ws34 = ws34*sb_tests34;
      ws44 = ws44*sb_tests44;
      ws54 = ws54*sb_tests54;
      ws64 = ws64*sb_tests64;
      ws74 = ws74*sb_tests74;
      ws84 = ws84*sb_tests84;
      ws94 = ws94*sb_tests94;
      wsa4 = wsa4*sb_testsa4;
      wsb4 = wsb4*sb_testsb4;
      wsc4 = wsc4*sb_testsc4;
      wsd4 = wsd4*sb_testsd4;
      wse4 = wse4*sb_testse4;
      wsf4 = wsf4*sb_testsf4;

      U_3[k] = ws01+ws11+ws21+ws31
	       +ws41+ws51+ws61+ws71
	       +ws81+ws91+wsa1+wsb1
	       +wsc1+wsd1+wse1+wsf1
               +ws02+ws12+ws22+ws32
	       +ws42+ws52+ws62+ws72
	       +ws82+ws92+wsa2+wsb2
	       +wsc2+wsd2+wse2+wsf2
               +ws03+ws13+ws23+ws33
	       +ws43+ws53+ws63+ws73
	       +ws83+ws93+wsa3+wsb3
	       +wsc3+wsd3+wse3+wsf3
               +ws04+ws14+ws24+ws34
	       +ws44+ws54+ws64+ws74
	       +ws84+ws94+wsa4+wsb4
	       +wsc4+wsd4+wse4+wsf4;
    }
    __kernel void spread_save(__global const int *firstn1, __global const int *nextn1, __global const int *firstn2, __global const int *nextn2, __global const float *F_1, __global const float *F_2, __global const float *X_1, __global const float *X_2, const unsigned N, const float dx, const float dtheta, const unsigned shift0, const unsigned shift1, __global float *f_1, __global float *f_2)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;

      int k1 = firstn1[i+N*j]; 
      int k2 = firstn2[i+N*j]; 
      if (k1 == -1 && k2 == -1){
      return;
      }

      float c = dtheta/(dx*dx*dx);
      int ind_1x, ind_1y, ind_1z, ind_1w;
      int ind_2x, ind_2y, ind_2z, ind_2w;

      float f_10, f_11, f_12, f_13;
      float f_14, f_15, f_16, f_17;
      float f_18, f_19, f_1a, f_1b;
      float f_1c, f_1d, f_1e, f_1f;

      float f_20, f_21, f_22, f_23;
      float f_24, f_25, f_26, f_27;
      float f_28, f_29, f_2a, f_2b;
      float f_2c, f_2d, f_2e, f_2f;

      float v1x, v1y, v1z, v1w;
      float v2x, v2y, v2z, v2w;

      float q1, q2;

      float ws0, ws1, ws2, ws3;
      float ws4, ws5, ws6, ws7;
      float ws8, ws9, wsa, wsb;
      float wsc, wsd, wse, wsf;

      if (k1 !=-1){
      ind_1x = (i-1 & N-1);
      ind_1y = (i & N-1);
      ind_1z = (i+1 & N-1);
      ind_1w = (i+2 & N-1);

      ind_2x = (j-1 & N-1);
      ind_2y = (j & N-1);
      ind_2z = (j+1 & N-1);
      ind_2w = (j+2 & N-1);

      f_10=f_1[ind_1x+N*ind_2x];
      f_11=f_1[ind_1y+N*ind_2x];
      f_12=f_1[ind_1z+N*ind_2x];
      f_13=f_1[ind_1w+N*ind_2x];
      f_14=f_1[ind_1x+N*ind_2y];
      f_15=f_1[ind_1y+N*ind_2y];
      f_16=f_1[ind_1z+N*ind_2y];
      f_17=f_1[ind_1w+N*ind_2y];
      f_18=f_1[ind_1x+N*ind_2z];
      f_19=f_1[ind_1y+N*ind_2z];
      f_1a=f_1[ind_1z+N*ind_2z];
      f_1b=f_1[ind_1w+N*ind_2z];
      f_1c=f_1[ind_1x+N*ind_2w];
      f_1d=f_1[ind_1y+N*ind_2w];
      f_1e=f_1[ind_1z+N*ind_2w];
      f_1f=f_1[ind_1w+N*ind_2w];
      }

      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+0.5)/dx;
      int i_1_stag = convert_int(floor(s_1_stag));
      float r_1_stag = s_1_stag-i_1_stag;
      float s_2_c = (X_2[k1]+0.5-dx/2)/dx;        
      int i_2_c = convert_int(floor(s_2_c));
      float r_2_c = s_2_c-i_2_c;
      
      q1 = sqrt(1.+4.0*r_1_stag*(1-r_1_stag)); 
      q2 = sqrt(1.+4.0*r_2_c*(1-r_2_c));

      v1x = 3.-2.*r_1_stag-q1; 
      v1y = 3.-2.*r_1_stag+q1; 
      v1z = 1.+2.*r_1_stag+q1; 
      v1w = 1.+2.*r_1_stag-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_c-q2; 
      v2y = 3.-2.*r_2_c+q2; 
      v2z = 1.+2.*r_2_c+q2; 
      v2w = 1.+2.*r_2_c-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;
      
      ws0 = v1x*v2x;
      ws1 = v1y*v2x;
      ws2 = v1z*v2x;
      ws3 = v1w*v2x;
      ws4 = v1x*v2y;
      ws5 = v1y*v2y;
      ws6 = v1z*v2y;
      ws7 = v1w*v2y;
      ws8 = v1x*v2z;
      ws9 = v1y*v2z;
      wsa = v1z*v2z;
      wsb = v1w*v2z;
      wsc = v1x*v2w;
      wsd = v1y*v2w;
      wse = v1z*v2w;
      wsf = v1w*v2w;
      
      float my_F_1 = F_1[k1];
      f_10 += c*my_F_1*ws0;
      f_11 += c*my_F_1*ws1;
      f_12 += c*my_F_1*ws2;
      f_13 += c*my_F_1*ws3;
      f_14 += c*my_F_1*ws4;
      f_15 += c*my_F_1*ws5;
      f_16 += c*my_F_1*ws6;
      f_17 += c*my_F_1*ws7;
      f_18 += c*my_F_1*ws8;
      f_19 += c*my_F_1*ws9;
      f_1a += c*my_F_1*wsa;
      f_1b += c*my_F_1*wsb;
      f_1c += c*my_F_1*wsc;
      f_1d += c*my_F_1*wsd;
      f_1e += c*my_F_1*wse;
      f_1f += c*my_F_1*wsf;

      k1 = nextn1[k1];
      if (k1 == -1){
      f_1[ind_1x+N*ind_2x]=f_10;
      f_1[ind_1y+N*ind_2x]=f_11;
      f_1[ind_1z+N*ind_2x]=f_12;
      f_1[ind_1w+N*ind_2x]=f_13;
      f_1[ind_1x+N*ind_2y]=f_14;
      f_1[ind_1y+N*ind_2y]=f_15;
      f_1[ind_1z+N*ind_2y]=f_16;
      f_1[ind_1w+N*ind_2y]=f_17;
      f_1[ind_1x+N*ind_2z]=f_18;
      f_1[ind_1y+N*ind_2z]=f_19;
      f_1[ind_1z+N*ind_2z]=f_1a;
      f_1[ind_1w+N*ind_2z]=f_1b;
      f_1[ind_1x+N*ind_2w]=f_1c;
      f_1[ind_1y+N*ind_2w]=f_1d;
      f_1[ind_1z+N*ind_2w]=f_1e;
      f_1[ind_1w+N*ind_2w]=f_1f;
      }
      }

      if (k2 !=-1){
      ind_1x = (i-1 & N-1);
      ind_1y = (i & N-1);
      ind_1z = (i+1 & N-1);
      ind_1w = (i+2 & N-1);

      ind_2x = (j-1 & N-1);
      ind_2y = (j & N-1);
      ind_2z = (j+1 & N-1);
      ind_2w = (j+2 & N-1);

      f_20=f_2[ind_1x+N*ind_2x];
      f_21=f_2[ind_1y+N*ind_2x];
      f_22=f_2[ind_1z+N*ind_2x];
      f_23=f_2[ind_1w+N*ind_2x];
      f_24=f_2[ind_1x+N*ind_2y];
      f_25=f_2[ind_1y+N*ind_2y];
      f_26=f_2[ind_1z+N*ind_2y];
      f_27=f_2[ind_1w+N*ind_2y];
      f_28=f_2[ind_1x+N*ind_2z];
      f_29=f_2[ind_1y+N*ind_2z];
      f_2a=f_2[ind_1z+N*ind_2z];
      f_2b=f_2[ind_1w+N*ind_2z];
      f_2c=f_2[ind_1x+N*ind_2w];
      f_2d=f_2[ind_1y+N*ind_2w];
      f_2e=f_2[ind_1z+N*ind_2w];
      f_2f=f_2[ind_1w+N*ind_2w];
      }
      
      while (k2 != -1){
      float s_1_c = (X_1[k2]+0.5-dx/2)/dx;
      int i_1_c = convert_int(floor(s_1_c));
      float r_1_c = s_1_c-i_1_c;
      float s_2_stag = (X_2[k2]+0.5)/dx;        
      int i_2_stag = convert_int(floor(s_2_stag));
      float r_2_stag = s_2_stag-i_2_stag;

      q1 = sqrt(1.+4.0*r_1_c*(1-r_1_c)); 
      q2 = sqrt(1.+4.0*r_2_stag*(1-r_2_stag));

      v1x = 3.-2.*r_1_c-q1; 
      v1y = 3.-2.*r_1_c+q1; 
      v1z = 1.+2.*r_1_c+q1; 
      v1w = 1.+2.*r_1_c-q1; 
      v1x = v1x/8.;
      v1y = v1y/8.;
      v1z = v1z/8.;
      v1w = v1w/8.;

      v2x = 3.-2.*r_2_stag-q2; 
      v2y = 3.-2.*r_2_stag+q2; 
      v2z = 1.+2.*r_2_stag+q2; 
      v2w = 1.+2.*r_2_stag-q2; 
      v2x = v2x/8.;
      v2y = v2y/8.;
      v2z = v2z/8.;
      v2w = v2w/8.;
      
      ws0 = v1x*v2x;
      ws1 = v1y*v2x;
      ws2 = v1z*v2x;
      ws3 = v1w*v2x;
      ws4 = v1x*v2y;
      ws5 = v1y*v2y;
      ws6 = v1z*v2y;
      ws7 = v1w*v2y;
      ws8 = v1x*v2z;
      ws9 = v1y*v2z;
      wsa = v1z*v2z;
      wsb = v1w*v2z;
      wsc = v1x*v2w;
      wsd = v1y*v2w;
      wse = v1z*v2w;
      wsf = v1w*v2w;
      
      float my_F_2 = F_2[k2];
      f_20 += c*my_F_2*ws0;
      f_21 += c*my_F_2*ws1;
      f_22 += c*my_F_2*ws2;
      f_23 += c*my_F_2*ws3;
      f_24 += c*my_F_2*ws4;
      f_25 += c*my_F_2*ws5;
      f_26 += c*my_F_2*ws6;
      f_27 += c*my_F_2*ws7;
      f_28 += c*my_F_2*ws8;
      f_29 += c*my_F_2*ws9;
      f_2a += c*my_F_2*wsa;
      f_2b += c*my_F_2*wsb;
      f_2c += c*my_F_2*wsc;
      f_2d += c*my_F_2*wsd;
      f_2e += c*my_F_2*wse;
      f_2f += c*my_F_2*wsf;

      k2 = nextn2[k2];
      if (k2 == -1){
      f_2[ind_1x+N*ind_2x]=f_20;
      f_2[ind_1y+N*ind_2x]=f_21;
      f_2[ind_1z+N*ind_2x]=f_22;
      f_2[ind_1w+N*ind_2x]=f_23;
      f_2[ind_1x+N*ind_2y]=f_24;
      f_2[ind_1y+N*ind_2y]=f_25;
      f_2[ind_1z+N*ind_2y]=f_26;
      f_2[ind_1w+N*ind_2y]=f_27;
      f_2[ind_1x+N*ind_2z]=f_28;
      f_2[ind_1y+N*ind_2z]=f_29;
      f_2[ind_1z+N*ind_2z]=f_2a;
      f_2[ind_1w+N*ind_2z]=f_2b;
      f_2[ind_1x+N*ind_2w]=f_2c;
      f_2[ind_1y+N*ind_2w]=f_2d;
      f_2[ind_1z+N*ind_2w]=f_2e;
      f_2[ind_1w+N*ind_2w]=f_2f;
      }
      }
    }
    __kernel void updaten_col(__global int *firstn1, __global int *nextn1, __global int *firstn2, __global int *nextn2, __global int *firstn3, __global int *nextn3, __global const float *X_1, __global const float *X_2, const unsigned N1, const unsigned N2, const float dx1, const float dx2, const unsigned shift0, const unsigned shift1)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
     
      float L1 = N1*dx1;
      float L2 = N2*dx2;

      int k1 = firstn1[i+N1*j]; 
      int k2 = firstn2[i+N1*j]; 
      int k3 = firstn3[i+N1*j]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      uint ind_1, ind_2;
      int nextnold;

      int nprev1 = -1;
      while(k1 != -1)
      {
      float s_1_c = (X_1[k1]+L1*0.5-dx1/2)/dx1;
      int i_1_c = convert_int(floor(s_1_c));
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2)/dx2;        
      int i_2_c = convert_int(floor(s_2_c));
      
      ind_1 = (i_1_c & N1-1);
      ind_2 = (i_2_c & N2-1);

      if (ind_1 == i && ind_2 == j){
      nprev1 = k1;
      k1 = nextn1[k1];
      }
      else {
      nextnold = nextn1[k1];
      nextn1[k1] = firstn1[ind_1+N1*ind_2];
      firstn1[ind_1+N1*ind_2] = k1;
      k1 = nextnold;
          if (nprev1 == -1) {
          firstn1[i+N1*j] = nextnold;
          }
          else {
          nextn1[nprev1] = nextnold;
          }
      }
      }

      int nprev2 = -1;
      while(k2 != -1)
      {
      float s_1_stag = (X_1[k2]+L1*0.5)/dx1;
      int i_1_stag = convert_int(floor(s_1_stag));
      float s_2_c = (X_2[k2]+L2*0.5-dx2/2)/dx2;        
      int i_2_c = convert_int(floor(s_2_c));
      
      ind_1 = (i_1_stag & N1-1);
      ind_2 = (i_2_c & N2-1);

      if (ind_1 == i && ind_2 == j){
      nprev2 = k2;
      k2 = nextn2[k2];
      }
      else {
      nextnold = nextn2[k2];
      nextn2[k2] = firstn2[ind_1+N1*ind_2];
      firstn2[ind_1+N1*ind_2] = k2;
      k2 = nextnold;
          if (nprev2 == -1) {
          firstn2[i+N1*j] = nextnold;
          }
          else {
          nextn2[nprev2] = nextnold;
          }
      }
      }

      int nprev3 = -1;
      while(k3 != -1)
      {
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2)/dx1;
      int i_1_c = convert_int(floor(s_1_c));
      float s_2_stag = (X_2[k3]+L2*0.5)/dx2;        
      int i_2_stag = convert_int(floor(s_2_stag));
      
      ind_1 = (i_1_c & N1-1);
      ind_2 = (i_2_stag & N2-1);

      if (ind_1 == i && ind_2 == j){
      nprev3 = k3;
      k3 = nextn3[k3];
      }
      else {
      nextnold = nextn3[k3];
      nextn3[k3] = firstn3[ind_1+N1*ind_2];
      firstn3[ind_1+N1*ind_2] = k3;
      k3 = nextnold;
          if (nprev3 == -1) {
          firstn3[i+N1*j] = nextnold;
          }
          else {
          nextn3[nprev3] = nextnold;
          }
      }
    }
    }
    __kernel void updaten_spec(__global int *firstn, __global int *nextn, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N_pre_spec, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const unsigned shift0, const unsigned shift1, const unsigned shift2)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      unsigned k = 4*get_global_id(2)+shift2;
     
      float L1 = N1*dx1;
      float L2 = N2*dx2;
      float L3 = N3*dx3;

      int kk = firstn[i+N1*j+N1*N2*k]; 

      uint ind_1, ind_2, ind_3;
      int nextnold;

      int nprev1 = -1;
      while(kk != -1)
      {
      float s_1_stag = (X_1[kk+N_pre_spec]+L1*0.5)/dx1;
      int i_1_stag = convert_int(floor(s_1_stag));
      float s_2_stag = (X_2[kk+N_pre_spec]+L2*0.5)/dx2;
      int i_2_stag = convert_int(floor(s_2_stag));
      float s_3_stag = (X_3[kk+N_pre_spec]+L3*0.5)/dx3;
      int i_3_stag = convert_int(floor(s_3_stag));
      
      //ind_1 = (i_1_stag & N1-1);
      //ind_2 = (i_2_stag & N2-1);
      //ind_3 = (i_3_stag & N3-1);
      ind_1 = i_1_stag - N1*convert_int(floor(convert_float(i_1_stag)/convert_float(N1)));
      ind_2 = i_2_stag - N2*convert_int(floor(convert_float(i_2_stag)/convert_float(N2)));
      ind_3 = i_3_stag - N3*convert_int(floor(convert_float(i_3_stag)/convert_float(N3)));

      if (ind_1 == i && ind_2 == j && ind_3 == k){
      nprev1 = kk;
      kk = nextn[kk];
      }
      else {
      nextnold = nextn[kk];
      nextn[kk] = firstn[ind_1+N1*ind_2+N1*N2*ind_3];
      firstn[ind_1+N1*ind_2+N1*N2*ind_3] = kk;
      kk = nextnold;
          if (nprev1 == -1) {
          firstn[i+N1*j+N1*N2*k] = nextnold;
          }
          else {
          nextn[nprev1] = nextnold;
          }
      }
      }
    }
    __kernel void updaten(__global int *firstn1, __global int *nextn1, __global int *firstn2, __global int *nextn2, __global int *firstn3, __global int *nextn3, __global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const unsigned shift0, const unsigned shift1, const unsigned shift2)
    {
      unsigned i = 4*get_global_id(0)+shift0;
      unsigned j = 4*get_global_id(1)+shift1;
      unsigned k = 4*get_global_id(2)+shift2;
     
      float L1 = N1*dx1;
      float L2 = N2*dx2;
      float L3 = N3*dx3;

      int k1 = firstn1[i+N1*j+N1*N2*k]; 
      int k2 = firstn2[i+N1*j+N1*N2*k]; 
      int k3 = firstn3[i+N1*j+N1*N2*k]; 

      if (k1 == -1 && k2 == -1 && k3 == -1){
      return;
      }

      uint ind_1, ind_2, ind_3;
      int nextnold;

      int nprev1 = -1;
      while(k1 != -1)
      {
      float s_1_stag = (X_1[k1]+L1*0.5)/dx1;
      int i_1_stag = convert_int(floor(s_1_stag));
      float s_2_c = (X_2[k1]+L2*0.5-dx2/2)/dx2;        
      int i_2_c = convert_int(floor(s_2_c));
      float s_3_c = (X_3[k1]+L3*0.5-dx3/2)/dx3;        
      int i_3_c = convert_int(floor(s_3_c));
      
      ind_1 = (i_1_stag & N1-1);
      ind_2 = (i_2_c & N2-1);
      ind_3 = (i_3_c & N3-1);

      if (ind_1 == i && ind_2 == j && ind_3 == k){
      nprev1 = k1;
      k1 = nextn1[k1];
      }
      else {
      nextnold = nextn1[k1];
      nextn1[k1] = firstn1[ind_1+N1*ind_2+N1*N2*ind_3];
      firstn1[ind_1+N1*ind_2+N1*N2*ind_3] = k1;
      k1 = nextnold;
          if (nprev1 == -1) {
          firstn1[i+N1*j+N1*N2*k] = nextnold;
          }
          else {
          nextn1[nprev1] = nextnold;
          }
      }
      }

      int nprev2 = -1;
      while(k2 != -1)
      {
      float s_1_c = (X_1[k2]+L1*0.5-dx1/2)/dx1;
      int i_1_c = convert_int(floor(s_1_c));
      float s_2_stag = (X_2[k2]+L2*0.5)/dx2;        
      int i_2_stag = convert_int(floor(s_2_stag));
      float s_3_c = (X_3[k2]+L3*0.5-dx3/2)/dx3;
      int i_3_c = convert_int(floor(s_3_c));
      
      ind_1 = (i_1_c & N1-1);
      ind_2 = (i_2_stag & N2-1);
      ind_3 = (i_3_c & N3-1);

      if (ind_1 == i && ind_2 == j && ind_3 == k){
      nprev2 = k2;
      k2 = nextn2[k2];
      }
      else {
      nextnold = nextn2[k2];
      nextn2[k2] = firstn2[ind_1+N1*ind_2+N1*N2*ind_3];
      firstn2[ind_1+N1*ind_2+N1*N2*ind_3] = k2;
      k2 = nextnold;
          if (nprev2 == -1) {
          firstn2[i+N1*j+N1*N2*k] = nextnold;
          }
          else {
          nextn2[nprev2] = nextnold;
          }
      }
      }

      int nprev3 = -1;
      while(k3 != -1)
      {
      float s_1_c = (X_1[k3]+L1*0.5-dx1/2)/dx1;
      int i_1_c = convert_int(floor(s_1_c));
      float s_2_c = (X_2[k3]+L2*0.5-dx2/2)/dx2;        
      int i_2_c = convert_int(floor(s_2_c));
      float s_3_stag = (X_3[k3]+L3*0.5)/dx3;
      int i_3_stag = convert_int(floor(s_3_stag));
      
      ind_1 = (i_1_c & N1-1);
      ind_2 = (i_2_c & N2-1);
      ind_3 = (i_3_stag & N3-1);

      if (ind_1 == i && ind_2 == j && ind_3 == k){
      nprev3 = k3;
      k3 = nextn3[k3];
      }
      else {
      nextnold = nextn3[k3];
      nextn3[k3] = firstn3[ind_1+N1*ind_2+N1*N2*ind_3];
      firstn3[ind_1+N1*ind_2+N1*N2*ind_3] = k3;
      k3 = nextnold;
          if (nprev3 == -1) {
          firstn3[i+N1*j+N1*N2*k] = nextnold;
          }
          else {
          nextn3[nprev3] = nextnold;
          }
      }
    }
    }
    __kernel void count_make_distr(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *firstn, __global const int *nextn, const unsigned N_pre_spec, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float L_cont, __global int *count_el, const unsigned pre_ind)
    {
    unsigned k = get_global_id(0)+pre_ind;
    unsigned el_ind=0;
    int kk;
    unsigned ii;
    unsigned ind_1[3];
    unsigned ind_2[3];
    unsigned ind_3[3];
    float Rsq;
    float X1 = X_1[k+N_pre_spec];
    float X2 = X_2[k+N_pre_spec];
    float X3 = X_3[k+N_pre_spec];

    float L1 = N1*dx1;
    float L2 = N2*dx2;
    float L3 = N3*dx3;

    float s_1_stag = (X1+L1*0.5)/dx1;
    int i_1_stag = convert_int(floor(s_1_stag));
    float s_2_stag = (X2+L2*0.5)/dx2;        
    int i_2_stag = convert_int(floor(s_2_stag));
    float s_3_stag = (X3+L3*0.5)/dx3;        
    int i_3_stag = convert_int(floor(s_3_stag));

    //ind_1[0] = ((i_1_stag-1) & N1-1);
    //ind_2[0] = ((i_2_stag-1) & N2-1);
    //ind_3[0] = ((i_3_stag-1) & N3-1);
    //ind_1[1] = (i_1_stag & N1-1);
    //ind_2[1] = (i_2_stag & N2-1);
    //ind_3[1] = (i_3_stag & N3-1);
    //ind_1[2] = ((i_1_stag+1) & N1-1);
    //ind_2[2] = ((i_2_stag+1) & N2-1);
    //ind_3[2] = ((i_3_stag+1) & N3-1);
    ind_1[0] = (i_1_stag-1) - N1*convert_int(floor(convert_float(i_1_stag-1)/convert_float(N1)));
    ind_2[0] = (i_2_stag-1) - N2*convert_int(floor(convert_float(i_2_stag-1)/convert_float(N2)));
    ind_3[0] = (i_3_stag-1) - N3*convert_int(floor(convert_float(i_3_stag-1)/convert_float(N3)));
    ind_1[1] = (i_1_stag) - N1*convert_int(floor(convert_float(i_1_stag)/convert_float(N1)));
    ind_2[1] = (i_2_stag) - N2*convert_int(floor(convert_float(i_2_stag)/convert_float(N2)));
    ind_3[1] = (i_3_stag) - N3*convert_int(floor(convert_float(i_3_stag)/convert_float(N3)));
    ind_1[2] = (i_1_stag+1) - N1*convert_int(floor(convert_float(i_1_stag+1)/convert_float(N1)));
    ind_2[2] = (i_2_stag+1) - N2*convert_int(floor(convert_float(i_2_stag+1)/convert_float(N2)));
    ind_3[2] = (i_3_stag+1) - N3*convert_int(floor(convert_float(i_3_stag+1)/convert_float(N3)));
    
    for (unsigned i1=0; i1<3; i1++){
    for (unsigned i2=0; i2<3; i2++){
    for (unsigned i3=0; i3<3; i3++){
    kk = firstn[ind_1[i1]+N1*ind_2[i2]+N1*N2*ind_3[i3]];
    while(kk != -1) {
      if (kk == k) {
        kk = nextn[kk];
        continue; 
      }
      Rsq = (X1-X_1[N_pre_spec+kk])*(X1-X_1[N_pre_spec+kk])
           +(X2-X_2[N_pre_spec+kk])*(X2-X_2[N_pre_spec+kk])
           +(X3-X_3[N_pre_spec+kk])*(X3-X_3[N_pre_spec+kk]);
      if (Rsq < L_cont*L_cont){
        el_ind += 1;
      }
      kk = nextn[kk];
    }
    }
    }
    }
    count_el[k] = el_ind;
    }
    __kernel void count_make(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *firstn, __global const int *nextn, const unsigned N_pre_spec, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float L_cont, __global const int *CX, __global int *count_el, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned k = get_global_id(0)+pre_ind;
    unsigned el_ind=0;
    int kk;
    unsigned ii, flag;
    unsigned ind_1[3];
    unsigned ind_2[3];
    unsigned ind_3[3];
    float Rsq;
    float X1 = X_1[k+N_pre_spec];
    float X2 = X_2[k+N_pre_spec];
    float X3 = X_3[k+N_pre_spec];

    float L1 = N1*dx1;
    float L2 = N2*dx2;
    float L3 = N3*dx3;

    float s_1_stag = (X1+L1*0.5)/dx1;
    int i_1_stag = convert_int(floor(s_1_stag));
    float s_2_stag = (X2+L2*0.5)/dx2;        
    int i_2_stag = convert_int(floor(s_2_stag));
    float s_3_stag = (X3+L3*0.5)/dx3;        
    int i_3_stag = convert_int(floor(s_3_stag));

    //ind_1[0] = ((i_1_stag-1) & N1-1);
    //ind_2[0] = ((i_2_stag-1) & N2-1);
    //ind_3[0] = ((i_3_stag-1) & N3-1);
    //ind_1[1] = (i_1_stag & N1-1);
    //ind_2[1] = (i_2_stag & N2-1);
    //ind_3[1] = (i_3_stag & N3-1);
    //ind_1[2] = ((i_1_stag+1) & N1-1);
    //ind_2[2] = ((i_2_stag+1) & N2-1);
    //ind_3[2] = ((i_3_stag+1) & N3-1);
    ind_1[0] = (i_1_stag-1) - N1*convert_int(floor(convert_float(i_1_stag-1)/convert_float(N1)));
    ind_2[0] = (i_2_stag-1) - N2*convert_int(floor(convert_float(i_2_stag-1)/convert_float(N2)));
    ind_3[0] = (i_3_stag-1) - N3*convert_int(floor(convert_float(i_3_stag-1)/convert_float(N3)));
    ind_1[1] = (i_1_stag) - N1*convert_int(floor(convert_float(i_1_stag)/convert_float(N1)));
    ind_2[1] = (i_2_stag) - N2*convert_int(floor(convert_float(i_2_stag)/convert_float(N2)));
    ind_3[1] = (i_3_stag) - N3*convert_int(floor(convert_float(i_3_stag)/convert_float(N3)));
    ind_1[2] = (i_1_stag+1) - N1*convert_int(floor(convert_float(i_1_stag+1)/convert_float(N1)));
    ind_2[2] = (i_2_stag+1) - N2*convert_int(floor(convert_float(i_2_stag+1)/convert_float(N2)));
    ind_3[2] = (i_3_stag+1) - N3*convert_int(floor(convert_float(i_3_stag+1)/convert_float(N3)));
    
    for (unsigned i1=0; i1<3; i1++){
    for (unsigned i2=0; i2<3; i2++){
    for (unsigned i3=0; i3<3; i3++){
    kk = firstn[ind_1[i1]+N1*ind_2[i2]+N1*N2*ind_3[i3]];
    while(kk != -1) {
      flag = 0;
      ii = 0;
      while (ii < CX_max && CX[ii+CX_max*k] != -1) { 
        if (CX[ii+CX_max*k] == kk) {
          flag = 1;
          break;
        }
        ii += 1;
      }
      if (flag == 1 || kk == k) {
        kk = nextn[kk];
        continue; 
      }
      Rsq = (X1-X_1[N_pre_spec+kk])*(X1-X_1[N_pre_spec+kk])
           +(X2-X_2[N_pre_spec+kk])*(X2-X_2[N_pre_spec+kk])
           +(X3-X_3[N_pre_spec+kk])*(X3-X_3[N_pre_spec+kk]);
      if (Rsq < L_cont*L_cont){
        el_ind += 1;
      }
      kk = nextn[kk];
    }
    }
    }
    }
    count_el[k] = el_ind;
    }
    __kernel void fill_make_distr(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *firstn, __global const int *nextn, const unsigned N_pre_spec, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float L_cont, __global const int *el_inds, __global int *CX_el, const unsigned pre_ind)
    {
    unsigned k = get_global_id(0)+pre_ind;
    unsigned st_ind, el_ind=0;
    int kk;
    unsigned ii;
    unsigned ind_1[3];
    unsigned ind_2[3];
    unsigned ind_3[3];
    float Rsq;
    float X1 = X_1[k+N_pre_spec];
    float X2 = X_2[k+N_pre_spec];
    float X3 = X_3[k+N_pre_spec];

    if (k == 0) {
      st_ind = 0;
    }
    else {
      st_ind = el_inds[k-1];
    }

    float L1 = N1*dx1;
    float L2 = N2*dx2;
    float L3 = N3*dx3;

    float s_1_stag = (X1+L1*0.5)/dx1;
    int i_1_stag = convert_int(floor(s_1_stag));
    float s_2_stag = (X2+L2*0.5)/dx2;        
    int i_2_stag = convert_int(floor(s_2_stag));
    float s_3_stag = (X3+L3*0.5)/dx3;        
    int i_3_stag = convert_int(floor(s_3_stag));

    //ind_1[0] = ((i_1_stag-1) & N1-1);
    //ind_2[0] = ((i_2_stag-1) & N2-1);
    //ind_3[0] = ((i_3_stag-1) & N3-1);
    //ind_1[1] = (i_1_stag & N1-1);
    //ind_2[1] = (i_2_stag & N2-1);
    //ind_3[1] = (i_3_stag & N3-1);
    //ind_1[2] = ((i_1_stag+1) & N1-1);
    //ind_2[2] = ((i_2_stag+1) & N2-1);
    //ind_3[2] = ((i_3_stag+1) & N3-1);
    ind_1[0] = (i_1_stag-1) - N1*convert_int(floor(convert_float(i_1_stag-1)/convert_float(N1)));
    ind_2[0] = (i_2_stag-1) - N2*convert_int(floor(convert_float(i_2_stag-1)/convert_float(N2)));
    ind_3[0] = (i_3_stag-1) - N3*convert_int(floor(convert_float(i_3_stag-1)/convert_float(N3)));
    ind_1[1] = (i_1_stag) - N1*convert_int(floor(convert_float(i_1_stag)/convert_float(N1)));
    ind_2[1] = (i_2_stag) - N2*convert_int(floor(convert_float(i_2_stag)/convert_float(N2)));
    ind_3[1] = (i_3_stag) - N3*convert_int(floor(convert_float(i_3_stag)/convert_float(N3)));
    ind_1[2] = (i_1_stag+1) - N1*convert_int(floor(convert_float(i_1_stag+1)/convert_float(N1)));
    ind_2[2] = (i_2_stag+1) - N2*convert_int(floor(convert_float(i_2_stag+1)/convert_float(N2)));
    ind_3[2] = (i_3_stag+1) - N3*convert_int(floor(convert_float(i_3_stag+1)/convert_float(N3)));
    
    for (unsigned i1=0; i1<3; i1++){
    for (unsigned i2=0; i2<3; i2++){
    for (unsigned i3=0; i3<3; i3++){
    kk = firstn[ind_1[i1]+N1*ind_2[i2]+N1*N2*ind_3[i3]];
    while(kk != -1) {
      if (kk == k) {
        kk = nextn[kk];
        continue; 
      }
      Rsq = (X1-X_1[N_pre_spec+kk])*(X1-X_1[N_pre_spec+kk])
           +(X2-X_2[N_pre_spec+kk])*(X2-X_2[N_pre_spec+kk])
           +(X3-X_3[N_pre_spec+kk])*(X3-X_3[N_pre_spec+kk]);
      if (Rsq < L_cont*L_cont){
        CX_el[el_ind+st_ind] = kk; 
        el_ind += 1;
      }
      kk = nextn[kk];
    }
    }
    }
    }
    }
    __kernel void fill_make_new(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *firstn, __global const int *nextn, const unsigned N_pre_spec, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float L_cont, __global const int *CX, __global const int *el_inds, __global int *CX_el, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned k = get_global_id(0)+pre_ind;
    unsigned st_ind, el_ind=0;
    int kk;
    unsigned ii, flag;
    unsigned ind_1[3];
    unsigned ind_2[3];
    unsigned ind_3[3];
    float Rsq;
    float X1 = X_1[k+N_pre_spec];
    float X2 = X_2[k+N_pre_spec];
    float X3 = X_3[k+N_pre_spec];

    if (k == 0) {
      st_ind = 0;
    }
    else {
      st_ind = el_inds[k-1];
    }

    float L1 = N1*dx1;
    float L2 = N2*dx2;
    float L3 = N3*dx3;

    float s_1_stag = (X1+L1*0.5)/dx1;
    int i_1_stag = convert_int(floor(s_1_stag));
    float s_2_stag = (X2+L2*0.5)/dx2;        
    int i_2_stag = convert_int(floor(s_2_stag));
    float s_3_stag = (X3+L3*0.5)/dx3;        
    int i_3_stag = convert_int(floor(s_3_stag));

    //ind_1[0] = ((i_1_stag-1) & N1-1);
    //ind_2[0] = ((i_2_stag-1) & N2-1);
    //ind_3[0] = ((i_3_stag-1) & N3-1);
    //ind_1[1] = (i_1_stag & N1-1);
    //ind_2[1] = (i_2_stag & N2-1);
    //ind_3[1] = (i_3_stag & N3-1);
    //ind_1[2] = ((i_1_stag+1) & N1-1);
    //ind_2[2] = ((i_2_stag+1) & N2-1);
    //ind_3[2] = ((i_3_stag+1) & N3-1);
    ind_1[0] = (i_1_stag-1) - N1*convert_int(floor(convert_float(i_1_stag-1)/convert_float(N1)));
    ind_2[0] = (i_2_stag-1) - N2*convert_int(floor(convert_float(i_2_stag-1)/convert_float(N2)));
    ind_3[0] = (i_3_stag-1) - N3*convert_int(floor(convert_float(i_3_stag-1)/convert_float(N3)));
    ind_1[1] = (i_1_stag) - N1*convert_int(floor(convert_float(i_1_stag)/convert_float(N1)));
    ind_2[1] = (i_2_stag) - N2*convert_int(floor(convert_float(i_2_stag)/convert_float(N2)));
    ind_3[1] = (i_3_stag) - N3*convert_int(floor(convert_float(i_3_stag)/convert_float(N3)));
    ind_1[2] = (i_1_stag+1) - N1*convert_int(floor(convert_float(i_1_stag+1)/convert_float(N1)));
    ind_2[2] = (i_2_stag+1) - N2*convert_int(floor(convert_float(i_2_stag+1)/convert_float(N2)));
    ind_3[2] = (i_3_stag+1) - N3*convert_int(floor(convert_float(i_3_stag+1)/convert_float(N3)));
    
    for (unsigned i1=0; i1<3; i1++){
    for (unsigned i2=0; i2<3; i2++){
    for (unsigned i3=0; i3<3; i3++){
    kk = firstn[ind_1[i1]+N1*ind_2[i2]+N1*N2*ind_3[i3]];
    while(kk != -1) {
      flag = 0;
      ii = 0;
      while (ii < CX_max && CX[ii+CX_max*k] != -1) { 
        if (CX[ii+CX_max*k] == kk) {
          flag = 1;
          break;
        }
        ii += 1;
      }
      if (flag == 1 || kk == k) {
        kk = nextn[kk];
        continue; 
      }
      Rsq = (X1-X_1[N_pre_spec+kk])*(X1-X_1[N_pre_spec+kk])
           +(X2-X_2[N_pre_spec+kk])*(X2-X_2[N_pre_spec+kk])
           +(X3-X_3[N_pre_spec+kk])*(X3-X_3[N_pre_spec+kk]);
      if (Rsq < L_cont*L_cont){
        CX_el[el_ind+st_ind] = kk; 
        el_ind += 1;
      }
      kk = nextn[kk];
    }
    }
    }
    }
    }
    __kernel void fill_make(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *firstn, __global const int *nextn, const unsigned N_pre_spec, const unsigned N1, const unsigned N2, const unsigned N3, const float dx1, const float dx2, const float dx3, const float L_cont, __global const int *CX, __global int *CX_el, const unsigned CX_max, const unsigned CX_el_max, const unsigned pre_ind)
    {
    unsigned k = get_global_id(0)+pre_ind;
    unsigned el_ind=0;
    int kk;
    unsigned ii, flag;
    unsigned ind_1[3];
    unsigned ind_2[3];
    unsigned ind_3[3];
    float Rsq;
    float X1 = X_1[k+N_pre_spec];
    float X2 = X_2[k+N_pre_spec];
    float X3 = X_3[k+N_pre_spec];

    float L1 = N1*dx1;
    float L2 = N2*dx2;
    float L3 = N3*dx3;

    float s_1_stag = (X1+L1*0.5)/dx1;
    int i_1_stag = convert_int(floor(s_1_stag));
    float s_2_stag = (X2+L2*0.5)/dx2;        
    int i_2_stag = convert_int(floor(s_2_stag));
    float s_3_stag = (X3+L3*0.5)/dx3;        
    int i_3_stag = convert_int(floor(s_3_stag));

    //ind_1[0] = ((i_1_stag-1) & N1-1);
    //ind_2[0] = ((i_2_stag-1) & N2-1);
    //ind_3[0] = ((i_3_stag-1) & N3-1);
    //ind_1[1] = (i_1_stag & N1-1);
    //ind_2[1] = (i_2_stag & N2-1);
    //ind_3[1] = (i_3_stag & N3-1);
    //ind_1[2] = ((i_1_stag+1) & N1-1);
    //ind_2[2] = ((i_2_stag+1) & N2-1);
    //ind_3[2] = ((i_3_stag+1) & N3-1);
    ind_1[0] = (i_1_stag-1) - N1*convert_int(floor(convert_float(i_1_stag-1)/convert_float(N1)));
    ind_2[0] = (i_2_stag-1) - N2*convert_int(floor(convert_float(i_2_stag-1)/convert_float(N2)));
    ind_3[0] = (i_3_stag-1) - N3*convert_int(floor(convert_float(i_3_stag-1)/convert_float(N3)));
    ind_1[1] = (i_1_stag) - N1*convert_int(floor(convert_float(i_1_stag)/convert_float(N1)));
    ind_2[1] = (i_2_stag) - N2*convert_int(floor(convert_float(i_2_stag)/convert_float(N2)));
    ind_3[1] = (i_3_stag) - N3*convert_int(floor(convert_float(i_3_stag)/convert_float(N3)));
    ind_1[2] = (i_1_stag+1) - N1*convert_int(floor(convert_float(i_1_stag+1)/convert_float(N1)));
    ind_2[2] = (i_2_stag+1) - N2*convert_int(floor(convert_float(i_2_stag+1)/convert_float(N2)));
    ind_3[2] = (i_3_stag+1) - N3*convert_int(floor(convert_float(i_3_stag+1)/convert_float(N3)));
    
    for (unsigned i1=0; i1<3; i1++){
    for (unsigned i2=0; i2<3; i2++){
    for (unsigned i3=0; i3<3; i3++){
    kk = firstn[ind_1[i1]+N1*ind_2[i2]+N1*N2*ind_3[i3]];
    while(kk != -1) {
      flag = 0;
      ii = 0;
      while (ii < CX_max && CX[ii+CX_max*k] != -1) { 
        if (CX[ii+CX_max*k] == kk) {
          flag = 1;
          break;
        }
        ii += 1;
      }
      if (flag == 1 || kk == k) {
        kk = nextn[kk];
        continue; 
      }
      Rsq = (X1-X_1[N_pre_spec+kk])*(X1-X_1[N_pre_spec+kk])
           +(X2-X_2[N_pre_spec+kk])*(X2-X_2[N_pre_spec+kk])
           +(X3-X_3[N_pre_spec+kk])*(X3-X_3[N_pre_spec+kk]);
      if (Rsq < L_cont*L_cont){
        CX_el[el_ind+CX_el_max*k] = kk; 
        el_ind += 1;
      }
      kk = nextn[kk];
    }
    }
    }
    }
    }
    __kernel void symm_test(__global float *make_spec, __global const int *CX, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned j = get_global_id(1);
    unsigned l, k;

    if (CX[j+CX_max*i] != -1) {
       l = CX[j+CX_max*i];
       if (l < i) { //synch random nos
          //find correct index
          k = 0;
          while (k < CX_max && CX[k+CX_max*l] != -1) { 
             //if (CX[k+CX_max*l] == i) {
             //   make_spec[j+CX_max*i] = make_spec[k+CX_max*l]; 
             //   break;
             //}
             if (k == CX_max-1 & CX[k+CX_max*l] != i) {
                make_spec[0] = 1;
             }
             k += 1;
          }
       }
    }
    }
    __kernel void symm_make_spec_new(__global float *make_spec, __global const int *CX_el, __global const int *el_inds, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned l, st_ind, lst_ind;
    int k;
    unsigned ne, flag;

    if (i == 0) {
      st_ind = 0;
    }
    else {
      st_ind = el_inds[i-1];
    }

    if (i == 0) {
      ne = el_inds[0];
    }
    else {
      ne = el_inds[i]-el_inds[i-1];
    }
    
    for (unsigned j=0; j < ne; j++) {
      l = CX_el[j+st_ind];
      if (l < i) { //synch random nos
        if (l == 0) {
          lst_ind = 0;
        }
        else {
          lst_ind = el_inds[l-1];
        }
        k = 0;
        while (k >= 0) {
          if (CX_el[k+lst_ind] == i) {
            make_spec[j+st_ind] = make_spec[k+lst_ind];
            k = -1;
          }
          else {
            k += 1;
          }
        }
      }
    }
    }
    __kernel void symm_make_spec(__global float *make_spec, __global const int *CX, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned j = get_global_id(1);
    unsigned l, k;

    if (CX[j+CX_max*i] != -1) {
       l = CX[j+CX_max*i];
       if (l < i) { //synch random nos
          //find correct index
          k = 0;
          while (k < CX_max && CX[k+CX_max*l] != -1) { 
             if (CX[k+CX_max*l] == i) {
                make_spec[j+CX_max*i] = make_spec[k+CX_max*l]; 
                break;
             }
             k += 1;
          }
       }
    }
    }
    __kernel void symm_break_spec(__global float *break_spec, __global const int *CX, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned j = get_global_id(1);
    unsigned l, k;

    if (CX[j+CX_max*i] != -1) {
       l = CX[j+CX_max*i];
       if (l < i) { //synch random nos
          //find correct index
          k = 0;
          while (k < CX_max && CX[k+CX_max*l] != -1) { 
             if (CX[k+CX_max*l] == i) {
                break_spec[j+CX_max*i] = break_spec[k+CX_max*l]; 
                break;
             }
             k += 1;
          }
       }
    }
    }
    __kernel void monitor_spec(__global const int *CX, const unsigned CX_max, __global int *monitor)
    {
    unsigned i = get_global_id(0);
    unsigned ne = 0;

    while (ne < CX_max && CX[ne+CX_max*i] != -1) { 
      ne = ne+1;
    }
    monitor[i] = ne;
    } 
    __kernel void make_spec_new(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *CX_el, __global const float *make_spec, __global const float *myfun, const unsigned N_pre_spec, const unsigned tablesize, const float L_cont, const float kbrk, const float dt, __global int *CX, __global const int *el_inds, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned ne = 0;
    unsigned ii, st_ind;
    unsigned ne_el;

    float R, prob;

    float X1 = X_1[i+N_pre_spec];
    float X2 = X_2[i+N_pre_spec];
    float X3 = X_3[i+N_pre_spec];

    while (ne < CX_max && CX[ne+CX_max*i] != -1) { 
      ne = ne+1;
    }
    
    if (i == 0) {
      ne_el = el_inds[0];
    }
    else {
      ne_el = el_inds[i]-el_inds[i-1];
    }
    
    if (i == 0) {
      st_ind = 0;
    }
    else {
      st_ind = el_inds[i-1];
    }

    for (unsigned j=0; j < ne_el; j++) {
      ii = CX_el[j+st_ind];
      R = sqrt((X1-X_1[N_pre_spec+ii])*(X1-X_1[N_pre_spec+ii])
           +(X2-X_2[N_pre_spec+ii])*(X2-X_2[N_pre_spec+ii])
           +(X3-X_3[N_pre_spec+ii])*(X3-X_3[N_pre_spec+ii]));

      prob = myfun[convert_int(floor(R/L_cont*tablesize))]/R;

      if (make_spec[j+st_ind] < dt*kbrk*prob/(1.0-prob)) {
           if (ne == CX_max) { //should never happen
             break;
           }
           CX[ne+CX_max*i] = ii;
           ne += 1;
      }
    }
    }
    __kernel void make_spec(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *CX_el, __global const float *make_spec, __global const float *myfun, const unsigned N_pre_spec, const unsigned tablesize, const float L_cont, const float kbrk, const float dt, __global int *CX, const unsigned CX_el_max, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned ne = 0;
    unsigned ii, jj;

    float R, prob;

    float X1 = X_1[i+N_pre_spec];
    float X2 = X_2[i+N_pre_spec];
    float X3 = X_3[i+N_pre_spec];

    while (ne < CX_max && CX[ne+CX_max*i] != -1) { 
      ne = ne+1;
    }
    
    jj = 0;
    while (jj < CX_el_max && CX_el[jj+CX_el_max*i] != -1) { 
      ii = CX_el[jj+CX_el_max*i];
      R = sqrt((X1-X_1[N_pre_spec+ii])*(X1-X_1[N_pre_spec+ii])
           +(X2-X_2[N_pre_spec+ii])*(X2-X_2[N_pre_spec+ii])
           +(X3-X_3[N_pre_spec+ii])*(X3-X_3[N_pre_spec+ii]));
     // if (R < L_cont && R > 0) {
      prob = myfun[convert_int(floor(R/L_cont*tablesize))]/R;
     // }
     // else {
     //   prob = 0.0;
     // }
      if (make_spec[jj+CX_el_max*i] < dt*kbrk*prob/(1.0-prob)) {
           CX[ne+CX_max*i] = CX_el[jj+CX_el_max*i];
           ne += 1;
           if (ne == CX_max) { //should never happen
             break;
           }
      }
    jj += 1;
    }
    }
    __kernel void break_spec(__global const float *break_spec, const float kbrk, const float dt, __global int *CX, const unsigned CX_max, const unsigned pre_ind)
    {
    unsigned i = get_global_id(0)+pre_ind;
    unsigned ne = 0;
    unsigned ii, jj;

    while (ne < CX_max && CX[ne+CX_max*i] != -1) { 
    ne = ne+1;
    }
    
    for (unsigned j = 0; j < ne; j++) {
       jj = ne-1-j; 

       if (break_spec[jj+CX_max*i] < dt*kbrk) {
           CX[jj+CX_max*i] = -1;
           ii = jj;
           while(ii+1 < CX_max && CX[ii+1+CX_max*i] != -1) {
              CX[ii+CX_max*i] = CX[ii+1+CX_max*i];
              ii += 1;
              if (ii+1 == CX_max || CX[ii+1+CX_max*i] == -1) {
                 CX[ii+CX_max*i] = -1;
              }
           }
       }
    }
    }
    __kernel void calc_lagF_spec_new(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *CX, const unsigned CX_max, const unsigned N_pre, const float k_spec, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);
    unsigned j = 0;
    float F1 = 0.0;
    float F2 = 0.0;
    float F3 = 0.0;

    unsigned k;
    float R1, R2, R3;

    //first, calculate grad of i^th term of sum
    while (j < CX_max && CX[j+CX_max*i] != -1) { 
    k = CX[j+CX_max*i];

    R1 = X_1[N_pre+i]-X_1[N_pre+k];
    R2 = X_2[N_pre+i]-X_2[N_pre+k];
    R3 = X_3[N_pre+i]-X_3[N_pre+k];

    F1 += -k_spec*R1; 
    F2 += -k_spec*R2; 
    F3 += -k_spec*R3; 

    j = j+1;
    }

    F_1[i+N_pre] += F1; 
    F_2[i+N_pre] += F2; 
    F_3[i+N_pre] += F3; 
    }
    __kernel void calc_lagF_spec(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *fe_1, __global const unsigned *fe_2, __global const int *CE, const unsigned CE_max, const unsigned N_pre, const float k_spec, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);
    unsigned j = 0;
    float F1 = 0.0;
    float F2 = 0.0;
    float F3 = 0.0;

    unsigned k;
    float R1, R2, R3;

    //first, calculate grad of i^th term of sum
    while (j < CE_max && CE[j+CE_max*i] != -1) { 
    k = CE[j+CE_max*i];

    if (i == fe_1[k]){
    R1 = X_1[N_pre+i]-X_1[N_pre+fe_2[k]];
    R2 = X_2[N_pre+i]-X_2[N_pre+fe_2[k]];
    R3 = X_3[N_pre+i]-X_3[N_pre+fe_2[k]];
    }
    else {
    R1 = X_1[N_pre+i]-X_1[N_pre+fe_1[k]];
    R2 = X_2[N_pre+i]-X_2[N_pre+fe_1[k]];
    R3 = X_3[N_pre+i]-X_3[N_pre+fe_1[k]];
    }

    F1 += -k_spec*R1; 
    F2 += -k_spec*R2; 
    F3 += -k_spec*R3; 

    j = j+1;
    }

    F_1[i+N_pre] += F1; 
    F_2[i+N_pre] += F2; 
    F_3[i+N_pre] += F3; 
    }
    __kernel void calc_lagF_wlc_new(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const int *CX, const unsigned CX_max, const unsigned N_pre, const float k_spec, const float L_cont, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);
    unsigned j = 0;
    float F1 = 0.0;
    float F2 = 0.0;
    float F3 = 0.0;

    unsigned k;
    float R1, R2, R3;
    float norm;

    //first, calculate grad of i^th term of sum
    while (j < CX_max && CX[j+CX_max*i] != -1) { 
    k = CX[j+CX_max*i];

    R1 = X_1[N_pre+i]-X_1[N_pre+k];
    R2 = X_2[N_pre+i]-X_2[N_pre+k];
    R3 = X_3[N_pre+i]-X_3[N_pre+k];

    norm = sqrt(R1*R1+R2*R2+R3*R3);
    F1 += -k_spec*(0.25/((1.0-norm/L_cont)*(1.0-norm/L_cont))-0.25+norm/L_cont)*R1/norm; 
    F2 += -k_spec*(0.25/((1.0-norm/L_cont)*(1.0-norm/L_cont))-0.25+norm/L_cont)*R2/norm; 
    F3 += -k_spec*(0.25/((1.0-norm/L_cont)*(1.0-norm/L_cont))-0.25+norm/L_cont)*R3/norm; 

    j = j+1;
    }

    F_1[i+N_pre] += F1; 
    F_2[i+N_pre] += F2; 
    F_3[i+N_pre] += F3; 
    }
    __kernel void calc_lagF_wlc(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *fe_1, __global const unsigned *fe_2, __global const int *CE, const unsigned CE_max, const unsigned N_pre, const float k_spec, const float L_cont, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);
    unsigned j = 0;
    float F1 = 0.0;
    float F2 = 0.0;
    float F3 = 0.0;

    unsigned k;
    float R1, R2, R3;
    float norm;

    //first, calculate grad of i^th term of sum
    while (j < CE_max && CE[j+CE_max*i] != -1) { 
    k = CE[j+CE_max*i];

    if (i == fe_1[k]){
    R1 = X_1[N_pre+i]-X_1[N_pre+fe_2[k]];
    R2 = X_2[N_pre+i]-X_2[N_pre+fe_2[k]];
    R3 = X_3[N_pre+i]-X_3[N_pre+fe_2[k]];
    }
    else {
    R1 = X_1[N_pre+i]-X_1[N_pre+fe_1[k]];
    R2 = X_2[N_pre+i]-X_2[N_pre+fe_1[k]];
    R3 = X_3[N_pre+i]-X_3[N_pre+fe_1[k]];
    }

    norm = sqrt(R1*R1+R2*R2+R3*R3);
    F1 += -k_spec*(0.25/((1.0-norm/L_cont)*(1.0-norm/L_cont))-0.25+norm/L_cont)*R1/norm; 
    F2 += -k_spec*(0.25/((1.0-norm/L_cont)*(1.0-norm/L_cont))-0.25+norm/L_cont)*R2/norm; 
    F3 += -k_spec*(0.25/((1.0-norm/L_cont)*(1.0-norm/L_cont))-0.25+norm/L_cont)*R3/norm; 

    j = j+1;
    }

    F_1[i+N_pre] += F1; 
    F_2[i+N_pre] += F2; 
    F_3[i+N_pre] += F3; 
    }
    __kernel void proj_tri(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const unsigned *tri_ind, const unsigned N_pre, __global float *U_1, __global float *U_2, __global float *U_3)
    { 
    unsigned i = get_global_id(0);

    unsigned j_tri = tri_ind[i];

    float n1, n2, n3;
    float a1, a2, a3;
    float b1, b2, b3;
    float norm;

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    X_11 = X_1[TV_1[j_tri]];
    X_12 = X_2[TV_1[j_tri]];
    X_13 = X_3[TV_1[j_tri]];

    X_21 = X_1[TV_2[j_tri]];
    X_22 = X_2[TV_2[j_tri]];
    X_23 = X_3[TV_2[j_tri]];

    X_31 = X_1[TV_3[j_tri]];
    X_32 = X_2[TV_3[j_tri]];
    X_33 = X_3[TV_3[j_tri]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = (a2*b3-a3*b2);
    n2 = (a3*b1-a1*b3);
    n3 = (a1*b2-a2*b1);

    norm = sqrt(n1*n1+n2*n2+n3*n3);
    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    float dot = n1*U_1[i+N_pre]+n2*U_2[i+N_pre]+n3*U_3[i+N_pre];

    U_1[i+N_pre] = U_1[i+N_pre]-dot*U_1[i+N_pre]; 
    U_2[i+N_pre] = U_2[i+N_pre]-dot*U_2[i+N_pre]; 
    U_3[i+N_pre] = U_3[i+N_pre]-dot*U_3[i+N_pre]; 
    }
    __kernel void proj_sphere(__global const float *X_1, __global const float *X_2, __global const float *X_3, const unsigned N_pre_spec, __global float *U_1, __global float *U_2, __global float *U_3)
    { 
    unsigned i = get_global_id(0);

    float normsq = X_1[i]*X_1[i]+X_2[i]*X_2[i]+X_3[i]*X_3[i];
    float dot = X_1[i]*U_1[i]+X_2[i]*U_2[i]+X_3[i]*U_3[i];

    U_1[i] = U_1[i]-dot/normsq*X_1[i]; 
    U_2[i] = U_2[i]-dot/normsq*X_2[i]; 
    U_3[i] = U_3[i]-dot/normsq*X_3[i]; 
    }
    __kernel void calc_nrml(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *A_0, __global const int *CT, const unsigned CT_max, const float k_area, __global float *F_1, __global float *F_2, __global float *F_3, const unsigned N_pre)
    { 
    unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;

    unsigned j = 0;
    unsigned k;

    n1 = 0.0;
    n2 = 0.0;
    n3 = 0.0;

    while (j < CT_max && CT[j+CT_max*i] != -1) { 
    k = CT[j+CT_max*i];

    if (TV_1[k] == i) {
    X_11 = X_1[TV_1[k]+N_pre];
    X_12 = X_2[TV_1[k]+N_pre];
    X_13 = X_3[TV_1[k]+N_pre];

    X_21 = X_1[TV_2[k]+N_pre];
    X_22 = X_2[TV_2[k]+N_pre];
    X_23 = X_3[TV_2[k]+N_pre];

    X_31 = X_1[TV_3[k]+N_pre];
    X_32 = X_2[TV_3[k]+N_pre];
    X_33 = X_3[TV_3[k]+N_pre];
    }
    else if (TV_2[k] == i) {
    X_11 = X_1[TV_2[k]+N_pre];
    X_12 = X_2[TV_2[k]+N_pre];
    X_13 = X_3[TV_2[k]+N_pre];

    X_21 = X_1[TV_3[k]+N_pre];
    X_22 = X_2[TV_3[k]+N_pre];
    X_23 = X_3[TV_3[k]+N_pre];

    X_31 = X_1[TV_1[k]+N_pre];
    X_32 = X_2[TV_1[k]+N_pre];
    X_33 = X_3[TV_1[k]+N_pre];
    }
    else {
    X_11 = X_1[TV_3[k]+N_pre];
    X_12 = X_2[TV_3[k]+N_pre];
    X_13 = X_3[TV_3[k]+N_pre];

    X_21 = X_1[TV_1[k]+N_pre];
    X_22 = X_2[TV_1[k]+N_pre];
    X_23 = X_3[TV_1[k]+N_pre];

    X_31 = X_1[TV_2[k]+N_pre];
    X_32 = X_2[TV_2[k]+N_pre];
    X_33 = X_3[TV_2[k]+N_pre];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 += (a2*b3-a3*b2);
    n2 += (a3*b1-a1*b3);
    n3 += (a1*b2-a2*b1);

    j = j+1;
    }

    //F_1[i] = n1/6.0;
    //F_2[i] = n2/6.0;
    //F_3[i] = n3/6.0;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    F_1[i+N_pre] = n1/norm;
    F_2[i+N_pre] = n2/norm;
    F_3[i+N_pre] = n3/norm;
    }
    __kernel void calc_lagF_area(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *A_0, __global const int *CT, const unsigned CT_max, const float k_area, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;

    unsigned j = 0;
    unsigned k;

    while (j < CT_max && CT[j+CT_max*i] != -1) { 
    k = CT[j+CT_max*i];

    if (TV_1[k] == i) {
    X_11 = X_1[TV_1[k]];
    X_12 = X_2[TV_1[k]];
    X_13 = X_3[TV_1[k]];

    X_21 = X_1[TV_2[k]];
    X_22 = X_2[TV_2[k]];
    X_23 = X_3[TV_2[k]];

    X_31 = X_1[TV_3[k]];
    X_32 = X_2[TV_3[k]];
    X_33 = X_3[TV_3[k]];
    }
    else if (TV_2[k] == i) {
    X_11 = X_1[TV_2[k]];
    X_12 = X_2[TV_2[k]];
    X_13 = X_3[TV_2[k]];

    X_21 = X_1[TV_3[k]];
    X_22 = X_2[TV_3[k]];
    X_23 = X_3[TV_3[k]];

    X_31 = X_1[TV_1[k]];
    X_32 = X_2[TV_1[k]];
    X_33 = X_3[TV_1[k]];
    }
    else {
    X_11 = X_1[TV_3[k]];
    X_12 = X_2[TV_3[k]];
    X_13 = X_3[TV_3[k]];

    X_21 = X_1[TV_1[k]];
    X_22 = X_2[TV_1[k]];
    X_23 = X_3[TV_1[k]];

    X_31 = X_1[TV_2[k]];
    X_32 = X_2[TV_2[k]];
    X_33 = X_3[TV_2[k]];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);
    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_21-X_31;
    a2 = X_22-X_32;
    a3 = X_23-X_33;

    b1 = 0.5*(n2*a3-n3*a2);
    b2 = 0.5*(n3*a1-n1*a3);
    b3 = 0.5*(n1*a2-n2*a1);

    //F_1[i] += k_area*(0.5*norm-A_0[k])*b1; 
    //F_2[i] += k_area*(0.5*norm-A_0[k])*b2; 
    //F_3[i] += k_area*(0.5*norm-A_0[k])*b3; 
    F_1[i] += k_area*(1.0-0.5*norm/A_0[k])*b1*(-1.0)/A_0[k]; 
    F_2[i] += k_area*(1.0-0.5*norm/A_0[k])*b2*(-1.0)/A_0[k]; 
    F_3[i] += k_area*(1.0-0.5*norm/A_0[k])*b3*(-1.0)/A_0[k]; 

    j = j+1;
    }
    }
    __kernel void calc_change_area(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *A_0, const float k_area, const unsigned N_tri, __global float *en)
    { 
    unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;

    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    en[i] = (A_0[i]-0.5*norm)/A_0[i];
    }
    __kernel void calc_energy_area(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *A_0, const float k_area, const unsigned N_tri, __global float *en)
    { 
    //unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;

    for (unsigned i=0; i<N_tri; i++) {
    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    //en[0] += 0.5*k_area*(0.5*norm-A_0[i])*(0.5*norm-A_0[i]);
    en[0] += 0.5*k_area*(1.0-0.5*norm/A_0[i])*(1.0-0.5*norm/A_0[i]);
    }
    }
    __kernel void calc_total_area(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *A_0, const float k_area, const unsigned N_tri, __global float *en)
    { 
    //unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;

    for (unsigned i=0; i<N_tri; i++) {
    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    en[0] += 0.5*norm;
    }
    }
    __kernel void calc_lagF_hook(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *X_ref_1, __global const float *X_ref_2, __global const float *X_ref_3, __global const int *CT, const unsigned CT_max, const float k_bulk, const float k_shear, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm, area, fac;
    float a1, a2, a3;
    float b1, b2, b3;
    float c1, c2, c3;
    float d1, d2, d3;
    float e1, e2, e3;
    float da1, da2, da3;

    float Z_11, Z_12, Z_13;
    float Z_21, Z_22, Z_23;
    float Z_31, Z_32, Z_33;

    unsigned j = 0;
    unsigned k;

    while (j < CT_max && CT[j+CT_max*i] != -1) { 
    k = CT[j+CT_max*i];

    if (TV_1[k] == i) {
    X_11 = X_ref_1[TV_1[k]];
    X_12 = X_ref_2[TV_1[k]];
    X_13 = X_ref_3[TV_1[k]];

    X_21 = X_ref_1[TV_2[k]];
    X_22 = X_ref_2[TV_2[k]];
    X_23 = X_ref_3[TV_2[k]];

    X_31 = X_ref_1[TV_3[k]];
    X_32 = X_ref_2[TV_3[k]];
    X_33 = X_ref_3[TV_3[k]];
    }
    else if (TV_2[k] == i) {
    X_11 = X_ref_1[TV_2[k]];
    X_12 = X_ref_2[TV_2[k]];
    X_13 = X_ref_3[TV_2[k]];

    X_21 = X_ref_1[TV_3[k]];
    X_22 = X_ref_2[TV_3[k]];
    X_23 = X_ref_3[TV_3[k]];

    X_31 = X_ref_1[TV_1[k]];
    X_32 = X_ref_2[TV_1[k]];
    X_33 = X_ref_3[TV_1[k]];
    }
    else {
    X_11 = X_ref_1[TV_3[k]];
    X_12 = X_ref_2[TV_3[k]];
    X_13 = X_ref_3[TV_3[k]];

    X_21 = X_ref_1[TV_1[k]];
    X_22 = X_ref_2[TV_1[k]];
    X_23 = X_ref_3[TV_1[k]];

    X_31 = X_ref_1[TV_2[k]];
    X_32 = X_ref_2[TV_2[k]];
    X_33 = X_ref_3[TV_2[k]];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    c1 = X_21-X_31;
    c2 = X_22-X_32;
    c3 = X_23-X_33;

    d1 = -b1;
    d2 = -b2;
    d3 = -b3;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);
    area = 0.5*norm;

    if (TV_1[k] == i) {
    X_11 = X_1[TV_1[k]];
    X_12 = X_2[TV_1[k]];
    X_13 = X_3[TV_1[k]];

    X_21 = X_1[TV_2[k]];
    X_22 = X_2[TV_2[k]];
    X_23 = X_3[TV_2[k]];

    X_31 = X_1[TV_3[k]];
    X_32 = X_2[TV_3[k]];
    X_33 = X_3[TV_3[k]];
    }
    else if (TV_2[k] == i) {
    X_11 = X_1[TV_2[k]];
    X_12 = X_2[TV_2[k]];
    X_13 = X_3[TV_2[k]];

    X_21 = X_1[TV_3[k]];
    X_22 = X_2[TV_3[k]];
    X_23 = X_3[TV_3[k]];

    X_31 = X_1[TV_1[k]];
    X_32 = X_2[TV_1[k]];
    X_33 = X_3[TV_1[k]];
    }
    else {
    X_11 = X_1[TV_3[k]];
    X_12 = X_2[TV_3[k]];
    X_13 = X_3[TV_3[k]];

    X_21 = X_1[TV_1[k]];
    X_22 = X_2[TV_1[k]];
    X_23 = X_3[TV_1[k]];

    X_31 = X_1[TV_2[k]];
    X_32 = X_2[TV_2[k]];
    X_33 = X_3[TV_2[k]];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    e1 = X_21-X_31;
    e2 = X_22-X_32;
    e3 = X_23-X_33;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    da1 = 0.5/norm*((e1*e1+e2*e2+e3*e3)*-b1+(e1*b1+e2*b2+e3*b3)*e1); 
    da2 = 0.5/norm*((e1*e1+e2*e2+e3*e3)*-b2+(e1*b1+e2*b2+e3*b3)*e2); 
    da3 = 0.5/norm*((e1*e1+e2*e2+e3*e3)*-b3+(e1*b1+e2*b2+e3*b3)*e3); 
    fac = (b1*b1+b2*b2+b3*b3)*(c1*c1+c2*c2+c3*c3)+2.0*(c1*d1+c2*d2+c3*d3)*(b1*e1+b2*e2+b3*e3)+(e1*e1+e2*e2+e3*e3)*(d1*d1+d2*d2+d3*d3);

    F_1[i] += -k_bulk*(0.5*norm/area-1.0)*da1;
    F_2[i] += -k_bulk*(0.5*norm/area-1.0)*da2;
    F_3[i] += -k_bulk*(0.5*norm/area-1.0)*da3;
    F_1[i] += k_shear*(0.5*fac/(norm*norm)*da1-0.5/norm*((c1*c1+c2*c2+c3*c3)*-b1-(c1*d1+c2*d2+c3*d3)*e1));
    F_2[i] += k_shear*(0.5*fac/(norm*norm)*da2-0.5/norm*((c1*c1+c2*c2+c3*c3)*-b2-(c1*d1+c2*d2+c3*d3)*e2));
    F_3[i] += k_shear*(0.5*fac/(norm*norm)*da3-0.5/norm*((c1*c1+c2*c2+c3*c3)*-b3-(c1*d1+c2*d2+c3*d3)*e3));

    j = j+1;
    }
    }
    __kernel void calc_energy_hook(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const float *X_ref_1, __global const float *X_ref_2, __global const float *X_ref_3, const float k_bulk, const float k_shear, const unsigned N_tri, __global float *en)
    { 
    //unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float Z_11, Z_12, Z_13;
    float Z_21, Z_22, Z_23;
    float Z_31, Z_32, Z_33;

    float n1, n2, n3, norm, area, theta;
    float a1, a2, a3;
    float b1, b2, b3;
    float c1, c2, c3;
    float d1, d2, d3;
    float e1, e2, e3;

    for (unsigned i=0; i<N_tri; i++) {
    X_11 = X_ref_1[TV_1[i]];
    X_12 = X_ref_2[TV_1[i]];
    X_13 = X_ref_3[TV_1[i]];

    X_21 = X_ref_1[TV_2[i]];
    X_22 = X_ref_2[TV_2[i]];
    X_23 = X_ref_3[TV_2[i]];

    X_31 = X_ref_1[TV_3[i]];
    X_32 = X_ref_2[TV_3[i]];
    X_33 = X_ref_3[TV_3[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;
   
    c1 = X_21-X_31;
    c2 = X_22-X_32;
    c3 = X_23-X_33;

    d1 = -b1;
    d2 = -b2;
    d3 = -b3;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);
    area = 0.5*norm;

    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    e1 = X_21-X_31;
    e2 = X_22-X_32;
    e3 = X_23-X_33;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    en[0] += 0.5*k_bulk*(0.5*norm/area-1.0)*(0.5*norm/area-1.0)*area;
    en[0] += 0.5*k_shear*(((b1*b1+b2*b2+b3*b3)*(c1*c1+c2*c2+c3*c3)+2.0*(c1*d1+c2*d2+c3*d3)*(b1*e1+b2*e2+b3*e3)+(e1*e1+e2*e2+e3*e3)*(d1*d1+d2*d2+d3*d3))*0.5/norm-2.0*area);
    }
    }
    __kernel void calc_lagF_curv(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const int *CT, const unsigned CT_max, const float k_curv, __global float *F_1, __global float *F_2, __global float *F_3)
    { 
    unsigned i = get_global_id(0);
    //i = 0;

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;
    float c1, c2, c3;
    float l1, l2, l3;
    float m1, m2, m3;

    float H1, H2, H3;
    float A1, A2, A3;
    float area;

    A1 = 0;
    A2 = 0;
    A3 = 0;

    H1 = 0;
    H2 = 0;
    H3 = 0;

    area = 0;

    float dH_11=0.0, dH_12=0.0, dH_13=0.0;
    float dH_21=0.0, dH_22=0.0, dH_23=0.0;
    float dH_31=0.0, dH_32=0.0, dH_33=0.0;

    float dH_11_v2=0.0, dH_12_v2=0.0, dH_13_v2=0.0;
    float dH_21_v2=0.0, dH_22_v2=0.0, dH_23_v2=0.0;
    float dH_31_v2=0.0, dH_32_v2=0.0, dH_33_v2=0.0;

    float dH_11_v3=0.0, dH_12_v3=0.0, dH_13_v3=0.0;
    float dH_21_v3=0.0, dH_22_v3=0.0, dH_23_v3=0.0;
    float dH_31_v3=0.0, dH_32_v3=0.0, dH_33_v3=0.0;

    float dA_11=0.0, dA_12=0.0, dA_13=0.0;
    float dA_21=0.0, dA_22=0.0, dA_23=0.0;
    float dA_31=0.0, dA_32=0.0, dA_33=0.0;

    unsigned k, v2, v3, l, m, v2o, v3o;
    unsigned j = 0;

    //first, calculate grad of i^th term of sum
    while (j < CT_max && CT[j+CT_max*i] != -1) { 
    k = CT[j+CT_max*i];

    if (TV_1[k] == i) {
    X_11 = X_1[TV_1[k]];
    X_12 = X_2[TV_1[k]];
    X_13 = X_3[TV_1[k]];

    X_21 = X_1[TV_2[k]];
    X_22 = X_2[TV_2[k]];
    X_23 = X_3[TV_2[k]];

    X_31 = X_1[TV_3[k]];
    X_32 = X_2[TV_3[k]];
    X_33 = X_3[TV_3[k]];

    v2 = TV_2[k];
    v3 = TV_3[k];
    }
    else if (TV_2[k] == i) {
    X_11 = X_1[TV_2[k]];
    X_12 = X_2[TV_2[k]];
    X_13 = X_3[TV_2[k]];

    X_21 = X_1[TV_3[k]];
    X_22 = X_2[TV_3[k]];
    X_23 = X_3[TV_3[k]];

    X_31 = X_1[TV_1[k]];
    X_32 = X_2[TV_1[k]];
    X_33 = X_3[TV_1[k]];

    v2 = TV_3[k];
    v3 = TV_1[k];
    }
    else {
    X_11 = X_1[TV_3[k]];
    X_12 = X_2[TV_3[k]];
    X_13 = X_3[TV_3[k]];

    X_21 = X_1[TV_1[k]];
    X_22 = X_2[TV_1[k]];
    X_23 = X_3[TV_1[k]];

    X_31 = X_1[TV_2[k]];
    X_32 = X_2[TV_2[k]];
    X_33 = X_3[TV_2[k]];

    v2 = TV_1[k];
    v3 = TV_2[k];
    }

    //compute derivatives of unit normal

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    A1 += 0.5*n1;
    A2 += 0.5*n2;
    A3 += 0.5*n3;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    area += 1.0/6.0*norm;

    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_21-X_31;
    a2 = X_22-X_32;
    a3 = X_23-X_33;

    b1 = n2*a3-n3*a2;
    b2 = n3*a1-n1*a3;
    b3 = n1*a2-n2*a1;

    H1 += 0.5*b1; 
    H2 += 0.5*b2; 
    H3 += 0.5*b3; 

    a1 = X_31-X_21;
    a2 = X_32-X_22;
    a3 = X_33-X_23;

    b1 = 1.0;
    b2 = 0.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    dH_11 += 0.5*m1;
    dH_21 += 0.5*m2;
    dH_31 += 0.5*m3;

    b1 = 0.0;
    b2 = 1.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    dH_12 += 0.5*m1;
    dH_22 += 0.5*m2;
    dH_32 += 0.5*m3;

    b1 = 0.0;
    b2 = 0.0;
    b3 = 1.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    dH_13 += 0.5*m1;
    dH_23 += 0.5*m2;
    dH_33 += 0.5*m3;

    a1 = X_11-X_31;
    a2 = X_12-X_32;
    a3 = X_13-X_33;

    b1 = 1.0;
    b2 = 0.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 1.0;
    c2 = 0.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_11_v2 += 0.5*(m1+l1);
    dH_21_v2 += 0.5*(m2+l2);
    dH_31_v2 += 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 1.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = 1.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_12_v2 += 0.5*(m1+l1);
    dH_22_v2 += 0.5*(m2+l2);
    dH_32_v2 += 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 0.0;
    b3 = 1.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = 0.0;
    c3 = 1.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_13_v2 += 0.5*(m1+l1);
    dH_23_v2 += 0.5*(m2+l2);
    dH_33_v2 += 0.5*(m3+l3);

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = 1.0;
    b2 = 0.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = -1.0;
    c2 = 0.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_11_v3 += 0.5*(m1+l1);
    dH_21_v3 += 0.5*(m2+l2);
    dH_31_v3 += 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 1.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = -1.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_12_v3 += 0.5*(m1+l1);
    dH_22_v3 += 0.5*(m2+l2);
    dH_32_v3 += 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 0.0;
    b3 = 1.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = 0.0;
    c3 = -1.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_13_v3 += 0.5*(m1+l1);
    dH_23_v3 += 0.5*(m2+l2);
    dH_33_v3 += 0.5*(m3+l3);

    a1 = 1.0;
    a2 = 0.0;
    a3 = 0.0;

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_11 += 0.5*m1; 
    dA_21 += 0.5*m2; 
    dA_31 += 0.5*m3; 

    a1 = 0.0;
    a2 = 1.0;
    a3 = 0.0;

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_12 += 0.5*m1; 
    dA_22 += 0.5*m2; 
    dA_32 += 0.5*m3; 

    a1 = 0.0;
    a2 = 0.0;
    a3 = 1.0;

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_13 += 0.5*m1; 
    dA_23 += 0.5*m2; 
    dA_33 += 0.5*m3; 

    j += 1;
    }

    m1 = H1*dH_11+H2*dH_21+H3*dH_31;
    m2 = A1*A1+A2*A2+A3*A3;
    m3 = H1*H1+H2*H2+H3*H3;
    c1 = A1*dA_11+A2*dA_21+A3*dA_31;
    F_1[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/3.0*H1*m3/m2);
    //F_1[i] += 2.0*(m1*m2-m3*c1)/(m2*m2);
    //F_1[i] += 2.0*m1;
    //F_1[i] += 2.0*H2*dH_21;
    //F_1[i] += dH_21;

    m1 = H1*dH_12+H2*dH_22+H3*dH_32;
    c1 = A1*dA_12+A2*dA_22+A3*dA_32;
    F_2[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/3.0*H2*m3/m2);
    //F_2[i] += 2.0*(m1*m2-m3*c1)/(m2*m2);
    //F_2[i] += 2.0*m1;
    //F_2[i] += 2.0*H2*dH_22;
    //F_2[i] += dH_22;

    m1 = H1*dH_13+H2*dH_23+H3*dH_33;
    c1 = A1*dA_13+A2*dA_23+A3*dA_33;
    F_3[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/3.0*H3*m3/m2);
    //F_3[i] += 2.0*(m1*m2-m3*c1)/(m2*m2);
    //F_3[i] += 2.0*m1;
    //F_3[i] += 2.0*H2*dH_23;
    //F_3[i] += dH_23;

    j = 0;
    //next, calculate grad of v2^th, v3^th terms of sum with triangles touching i
    while (j < CT_max && CT[j+CT_max*i] != -1) { 
    k = CT[j+CT_max*i];

    if (TV_1[k] == i) {
    v2o = TV_2[k];
    v3o = TV_3[k];
    }
    else if (TV_2[k] == i) {
    v2o = TV_3[k];
    v3o = TV_1[k];
    }
    else {
    v2o = TV_1[k];
    v3o = TV_2[k];
    }

    A1 = 0;
    A2 = 0;
    A3 = 0;

    H1 = 0;
    H2 = 0;
    H3 = 0;

    area = 0;

    l = 0;
    while (l < CT_max && CT[l+CT_max*v2o] != -1) { 
    m = CT[l+CT_max*v2o];

    if (TV_1[m] == v2o) {
    X_11 = X_1[TV_1[m]];
    X_12 = X_2[TV_1[m]];
    X_13 = X_3[TV_1[m]];

    X_21 = X_1[TV_2[m]];
    X_22 = X_2[TV_2[m]];
    X_23 = X_3[TV_2[m]];

    X_31 = X_1[TV_3[m]];
    X_32 = X_2[TV_3[m]];
    X_33 = X_3[TV_3[m]];

    v2 = TV_2[m];
    v3 = TV_3[m];
    }
    else if (TV_2[m] == v2o) {
    X_11 = X_1[TV_2[m]];
    X_12 = X_2[TV_2[m]];
    X_13 = X_3[TV_2[m]];

    X_21 = X_1[TV_3[m]];
    X_22 = X_2[TV_3[m]];
    X_23 = X_3[TV_3[m]];

    X_31 = X_1[TV_1[m]];
    X_32 = X_2[TV_1[m]];
    X_33 = X_3[TV_1[m]];

    v2 = TV_3[m];
    v3 = TV_1[m];
    }
    else {
    X_11 = X_1[TV_3[m]];
    X_12 = X_2[TV_3[m]];
    X_13 = X_3[TV_3[m]];

    X_21 = X_1[TV_1[m]];
    X_22 = X_2[TV_1[m]];
    X_23 = X_3[TV_1[m]];

    X_31 = X_1[TV_2[m]];
    X_32 = X_2[TV_2[m]];
    X_33 = X_3[TV_2[m]];

    v2 = TV_1[m];
    v3 = TV_2[m];
    }
    //compute derivatives of unit normal

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    A1 += 0.5*n1;
    A2 += 0.5*n2;
    A3 += 0.5*n3;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    area += 1.0/6.0*norm;

    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_21-X_31;
    a2 = X_22-X_32;
    a3 = X_23-X_33;

    b1 = n2*a3-n3*a2;
    b2 = n3*a1-n1*a3;
    b3 = n1*a2-n2*a1;

    H1 += 0.5*b1; 
    H2 += 0.5*b2; 
    H3 += 0.5*b3; 

    l += 1;
    }
    //compute derivatives of unit normal

    if (TV_1[k] == v2o) {
    X_11 = X_1[TV_1[k]];
    X_12 = X_2[TV_1[k]];
    X_13 = X_3[TV_1[k]];

    X_21 = X_1[TV_2[k]];
    X_22 = X_2[TV_2[k]];
    X_23 = X_3[TV_2[k]];

    X_31 = X_1[TV_3[k]];
    X_32 = X_2[TV_3[k]];
    X_33 = X_3[TV_3[k]];
    }
    else if (TV_2[k] == v2o) {
    X_11 = X_1[TV_2[k]];
    X_12 = X_2[TV_2[k]];
    X_13 = X_3[TV_2[k]];

    X_21 = X_1[TV_3[k]];
    X_22 = X_2[TV_3[k]];
    X_23 = X_3[TV_3[k]];

    X_31 = X_1[TV_1[k]];
    X_32 = X_2[TV_1[k]];
    X_33 = X_3[TV_1[k]];
    }
    else {
    X_11 = X_1[TV_3[k]];
    X_12 = X_2[TV_3[k]];
    X_13 = X_3[TV_3[k]];

    X_21 = X_1[TV_1[k]];
    X_22 = X_2[TV_1[k]];
    X_23 = X_3[TV_1[k]];

    X_31 = X_1[TV_2[k]];
    X_32 = X_2[TV_2[k]];
    X_33 = X_3[TV_2[k]];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = 1.0;
    b2 = 0.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = -1.0;
    c2 = 0.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_11_v3 = 0.5*(m1+l1);
    dH_21_v3 = 0.5*(m2+l2);
    dH_31_v3 = 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 1.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = -1.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_12_v3 = 0.5*(m1+l1);
    dH_22_v3 = 0.5*(m2+l2);
    dH_32_v3 = 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 0.0;
    b3 = 1.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = 0.0;
    c3 = -1.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_13_v3 = 0.5*(m1+l1);
    dH_23_v3 = 0.5*(m2+l2);
    dH_33_v3 = 0.5*(m3+l3);

    a1 = 1.0;
    a2 = 0.0;
    a3 = 0.0;

    b1 = X_11-X_21;
    b2 = X_12-X_22;
    b3 = X_13-X_23;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_11 = 0.5*m1; 
    dA_21 = 0.5*m2; 
    dA_31 = 0.5*m3; 

    a1 = 0.0;
    a2 = 1.0;
    a3 = 0.0;

    b1 = X_11-X_21;
    b2 = X_12-X_22;
    b3 = X_13-X_23;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_12 = 0.5*m1; 
    dA_22 = 0.5*m2; 
    dA_32 = 0.5*m3; 

    a1 = 0.0;
    a2 = 0.0;
    a3 = 1.0;

    b1 = X_11-X_21;
    b2 = X_12-X_22;
    b3 = X_13-X_23;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_13 = 0.5*m1; 
    dA_23 = 0.5*m2; 
    dA_33 = 0.5*m3; 

    b1 = X_11-X_21;
    b2 = X_12-X_22;
    b3 = X_13-X_23;

    a1 = n2*b3-n3*b2;
    a2 = n3*b1-n1*b3;
    a3 = n1*b2-n2*b1;

    //if (v2o == 7) {
    m1 = H1*dH_11_v3+H2*dH_21_v3+H3*dH_31_v3;
    m2 = A1*A1+A2*A2+A3*A3;
    m3 = H1*H1+H2*H2+H3*H3;
    c1 = A1*dA_11+A2*dA_21+A3*dA_31;
    F_1[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/6.0*a1*m3/m2);
    //F_1[i] += 2.0*m1;
    //F_1[i] += 2.0*H1*dH_11_v3;
    //F_1[i] += dH_11_v3;
    //F_1[i] += dH_31_v3;

    m1 = H1*dH_12_v3+H2*dH_22_v3+H3*dH_32_v3;
    c1 = A1*dA_12+A2*dA_22+A3*dA_32;
    F_2[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/6.0*a2*m3/m2);
    //F_2[i] += 2.0*m1;
    //F_2[i] += 2.0*H1*dH_12_v3;
    //F_2[i] += dH_12_v3;
    //F_2[i] += dH_32_v3;

    m1 = H1*dH_13_v3+H2*dH_23_v3+H3*dH_33_v3;
    c1 = A1*dA_13+A2*dA_23+A3*dA_33;
    F_3[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/6.0*a3*m3/m2);
    //F_3[i] += 2.0*m1;
    //F_3[i] += 2.0*H1*dH_13_v3;
    //F_3[i] += dH_13_v3;
    //F_3[i] += dH_33_v3;
    //}

    A1 = 0;
    A2 = 0;
    A3 = 0;

    H1 = 0;
    H2 = 0;
    H3 = 0;

    area = 0;

    l = 0;
    while (l < CT_max && CT[l+CT_max*v3o] != -1) { 
    m = CT[l+CT_max*v3o];

    if (TV_1[m] == v3o) {
    X_11 = X_1[TV_1[m]];
    X_12 = X_2[TV_1[m]];
    X_13 = X_3[TV_1[m]];

    X_21 = X_1[TV_2[m]];
    X_22 = X_2[TV_2[m]];
    X_23 = X_3[TV_2[m]];

    X_31 = X_1[TV_3[m]];
    X_32 = X_2[TV_3[m]];
    X_33 = X_3[TV_3[m]];

    v2 = TV_2[m];
    v3 = TV_3[m];
    }
    else if (TV_2[m] == v3o) {
    X_11 = X_1[TV_2[m]];
    X_12 = X_2[TV_2[m]];
    X_13 = X_3[TV_2[m]];

    X_21 = X_1[TV_3[m]];
    X_22 = X_2[TV_3[m]];
    X_23 = X_3[TV_3[m]];

    X_31 = X_1[TV_1[m]];
    X_32 = X_2[TV_1[m]];
    X_33 = X_3[TV_1[m]];

    v2 = TV_3[m];
    v3 = TV_1[m];
    }
    else {
    X_11 = X_1[TV_3[m]];
    X_12 = X_2[TV_3[m]];
    X_13 = X_3[TV_3[m]];

    X_21 = X_1[TV_1[m]];
    X_22 = X_2[TV_1[m]];
    X_23 = X_3[TV_1[m]];

    X_31 = X_1[TV_2[m]];
    X_32 = X_2[TV_2[m]];
    X_33 = X_3[TV_2[m]];

    v2 = TV_1[m];
    v3 = TV_2[m];
    }
    //compute derivatives of unit normal

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    A1 += 0.5*n1;
    A2 += 0.5*n2;
    A3 += 0.5*n3;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    area += 1.0/6.0*norm;

    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_21-X_31;
    a2 = X_22-X_32;
    a3 = X_23-X_33;

    b1 = n2*a3-n3*a2;
    b2 = n3*a1-n1*a3;
    b3 = n1*a2-n2*a1;

    H1 += 0.5*b1; 
    H2 += 0.5*b2; 
    H3 += 0.5*b3; 

    l += 1;
    }
    //compute derivatives of unit normal

    if (TV_1[k] == v3o) {
    X_11 = X_1[TV_1[k]];
    X_12 = X_2[TV_1[k]];
    X_13 = X_3[TV_1[k]];

    X_21 = X_1[TV_2[k]];
    X_22 = X_2[TV_2[k]];
    X_23 = X_3[TV_2[k]];

    X_31 = X_1[TV_3[k]];
    X_32 = X_2[TV_3[k]];
    X_33 = X_3[TV_3[k]];
    }
    else if (TV_2[k] == v3o) {
    X_11 = X_1[TV_2[k]];
    X_12 = X_2[TV_2[k]];
    X_13 = X_3[TV_2[k]];

    X_21 = X_1[TV_3[k]];
    X_22 = X_2[TV_3[k]];
    X_23 = X_3[TV_3[k]];

    X_31 = X_1[TV_1[k]];
    X_32 = X_2[TV_1[k]];
    X_33 = X_3[TV_1[k]];
    }
    else {
    X_11 = X_1[TV_3[k]];
    X_12 = X_2[TV_3[k]];
    X_13 = X_3[TV_3[k]];

    X_21 = X_1[TV_1[k]];
    X_22 = X_2[TV_1[k]];
    X_23 = X_3[TV_1[k]];

    X_31 = X_1[TV_2[k]];
    X_32 = X_2[TV_2[k]];
    X_33 = X_3[TV_2[k]];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_11-X_31;
    a2 = X_12-X_32;
    a3 = X_13-X_33;

    b1 = 1.0;
    b2 = 0.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 1.0;
    c2 = 0.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_11_v2 = 0.5*(m1+l1);
    dH_21_v2 = 0.5*(m2+l2);
    dH_31_v2 = 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 1.0;
    b3 = 0.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = 1.0;
    c3 = 0.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_12_v2 = 0.5*(m1+l1);
    dH_22_v2 = 0.5*(m2+l2);
    dH_32_v2 = 0.5*(m3+l3);

    b1 = 0.0;
    b2 = 0.0;
    b3 = 1.0;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    c1 = 1.0/norm*(m1-n1*(n1*m1+n2*m2+n3*m3)); 
    c2 = 1.0/norm*(m2-n2*(n1*m1+n2*m2+n3*m3)); 
    c3 = 1.0/norm*(m3-n3*(n1*m1+n2*m2+n3*m3)); 

    b1 = X_21-X_31;
    b2 = X_22-X_32;
    b3 = X_23-X_33;

    m1 = c2*b3-c3*b2;
    m2 = c3*b1-c1*b3;
    m3 = c1*b2-c2*b1;

    c1 = 0.0;
    c2 = 0.0;
    c3 = 1.0;

    l1 = n2*c3-n3*c2;
    l2 = n3*c1-n1*c3;
    l3 = n1*c2-n2*c1;

    dH_13_v2 = 0.5*(m1+l1);
    dH_23_v2 = 0.5*(m2+l2);
    dH_33_v2 = 0.5*(m3+l3);

    a1 = 1.0;
    a2 = 0.0;
    a3 = 0.0;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_11 = 0.5*m1; 
    dA_21 = 0.5*m2; 
    dA_31 = 0.5*m3; 

    a1 = 0.0;
    a2 = 1.0;
    a3 = 0.0;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_12 = 0.5*m1; 
    dA_22 = 0.5*m2; 
    dA_32 = 0.5*m3; 

    a1 = 0.0;
    a2 = 0.0;
    a3 = 1.0;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    m1 = a2*b3-a3*b2;
    m2 = a3*b1-a1*b3;
    m3 = a1*b2-a2*b1;

    dA_13 = 0.5*m1; 
    dA_23 = 0.5*m2; 
    dA_33 = 0.5*m3; 

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    a1 = n2*b3-n3*b2;
    a2 = n3*b1-n1*b3;
    a3 = n1*b2-n2*b1;

    //if (v3o == 7) {
    m1 = H1*dH_11_v2+H2*dH_21_v2+H3*dH_31_v2;
    m2 = A1*A1+A2*A2+A3*A3;
    m3 = H1*H1+H2*H2+H3*H3;
    c1 = A1*dA_11+A2*dA_21+A3*dA_31;
    F_1[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/6.0*a1*m3/m2);
    //F_1[i] += 2.0*m1;
    //F_1[i] += 2.0*H1*dH_11_v2;
    //F_1[i] += dH_11_v2;
    //F_1[i] += dH_31_v2;

    m1 = H1*dH_12_v2+H2*dH_22_v2+H3*dH_32_v2;
    c1 = A1*dA_12+A2*dA_22+A3*dA_32;
    F_2[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/6.0*a2*m3/m2);
    //F_2[i] += 2.0*m1;
    //F_2[i] += 2.0*H1*dH_12_v2;
    //F_2[i] += dH_12_v2;
    //F_2[i] += dH_32_v2;

    m1 = H1*dH_13_v2+H2*dH_23_v2+H3*dH_33_v2;
    c1 = A1*dA_13+A2*dA_23+A3*dA_33;
    F_3[i] -= k_curv/2.0*(2.0*area*(m1*m2-m3*c1)/(m2*m2)-1.0/6.0*a3*m3/m2);
    //F_3[i] += 2.0*m1;
    //F_3[i] += 2.0*H1*dH_13_v2;
    //F_3[i] += dH_13_v2;
    //F_3[i] += dH_33_v2;
    //}

    j += 1;
    }
    }
    __kernel void calc_energy_curv(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const int *CT, const unsigned CT_max, const unsigned b_q, const float k_curv, __global float *en)
    { 
    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;
    float a1, a2, a3;
    float b1, b2, b3;

    float H1, H2, H3;
    float A1, A2, A3;
    float area;

    unsigned j, k;
    
    for (unsigned i=0; i<b_q; i++) {
    //debugging -- only do first vertex
    //for (unsigned i=0; i<1; i++) {
    //unsigned i=7;
    //calc H_p, A_p, area

    j = 0;

    A1 = 0;
    A2 = 0;
    A3 = 0;

    H1 = 0;
    H2 = 0;
    H3 = 0;

    area = 0;

    while (j < CT_max && CT[j+CT_max*i] != -1) { 
    k = CT[j+CT_max*i];

    if (TV_1[k] == i) {
    X_11 = X_1[TV_1[k]];
    X_12 = X_2[TV_1[k]];
    X_13 = X_3[TV_1[k]];

    X_21 = X_1[TV_2[k]];
    X_22 = X_2[TV_2[k]];
    X_23 = X_3[TV_2[k]];

    X_31 = X_1[TV_3[k]];
    X_32 = X_2[TV_3[k]];
    X_33 = X_3[TV_3[k]];
    }
    else if (TV_2[k] == i) {
    X_11 = X_1[TV_2[k]];
    X_12 = X_2[TV_2[k]];
    X_13 = X_3[TV_2[k]];

    X_21 = X_1[TV_3[k]];
    X_22 = X_2[TV_3[k]];
    X_23 = X_3[TV_3[k]];

    X_31 = X_1[TV_1[k]];
    X_32 = X_2[TV_1[k]];
    X_33 = X_3[TV_1[k]];
    }
    else {
    X_11 = X_1[TV_3[k]];
    X_12 = X_2[TV_3[k]];
    X_13 = X_3[TV_3[k]];

    X_21 = X_1[TV_1[k]];
    X_22 = X_2[TV_1[k]];
    X_23 = X_3[TV_1[k]];

    X_31 = X_1[TV_2[k]];
    X_32 = X_2[TV_2[k]];
    X_33 = X_3[TV_2[k]];
    }

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    A1 += 0.5*n1;
    A2 += 0.5*n2;
    A3 += 0.5*n3;

    norm = sqrt(n1*n1+n2*n2+n3*n3);

    area += 1.0/6.0*norm;

    n1 = n1/norm;
    n2 = n2/norm;
    n3 = n3/norm;

    a1 = X_21-X_31;
    a2 = X_22-X_32;
    a3 = X_23-X_33;

    b1 = n2*a3-n3*a2;
    b2 = n3*a1-n1*a3;
    b3 = n1*a2-n2*a1;

    H1 += 0.5*b1; 
    H2 += 0.5*b2; 
    H3 += 0.5*b3; 

    j += 1;
    }

    en[0] += k_curv/2.0*(H1*H1+H2*H2+H3*H3)/(A1*A1+A2*A2+A3*A3)*area; 
    //en[0] += (H1*H1+H2*H2+H3*H3)/(A1*A1+A2*A2+A3*A3); 
    //en[0] += (H1*H1+H2*H2+H3*H3); 
    //en[0] += H3; 
    }
    }
    __kernel void calc_energy_volume(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, const unsigned N_tri, __global float *en)
    { 
    //unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;

    float n1, n2, n3, norm;

    for (unsigned i=0; i<N_tri; i++) {
    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    n1 = X_22*X_33-X_23*X_32;
    n2 = X_23*X_31-X_21*X_33;
    n3 = X_21*X_32-X_22*X_31;

    norm = n1*X_11+n2*X_12+n3*X_13; 

    en[0] += 1.0/6.0*norm;
    }
    }
    __kernel void calc_coefs(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const unsigned *TV_4, __global const float *Rho, __global const float *Mu, const float dx1, const float dx2, const float dx3, const unsigned N1, const unsigned N2, const unsigned N3, __global float *rho_1, __global float *rho_2, __global float *rho_3, __global float *mu_1, __global float *mu_2, __global float *mu_3)
    { 
    unsigned i = get_global_id(0);

    //possible improvement--bring Rho, Mu, TV into local memory
    float L1 = dx1*N1;
    float L2 = dx2*N2;
    float L3 = dx3*N3;

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;
    float X_41, X_42, X_43;

    float mn1, mn2, mn3;
    float mx1, mx2, mx3;

    float gpt1, gpt2, gpt3;

    float p121, p122, p123;

    float chk121, chk122, chk123;
    float chk231, chk232, chk233;

    float dot1, dot2, dot3, dot4;

    int smn1, smn2, smn3; 
    int smx1, smx2, smx3; 

    uint ii,jj,kk;

    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    X_41 = X_1[TV_4[i]];
    X_42 = X_2[TV_4[i]];
    X_43 = X_3[TV_4[i]];

    //find candidate grid points
    mn1 = fmin(X_11,X_21);
    mn1 = fmin(mn1,X_31);
    mn1 = fmin(mn1,X_41);

    mn2 = fmin(X_12,X_22);
    mn2 = fmin(mn2,X_32);
    mn2 = fmin(mn2,X_42);

    mn3 = fmin(X_13,X_23);
    mn3 = fmin(mn3,X_33);
    mn3 = fmin(mn3,X_43);

    mx1 = fmax(X_11,X_21);
    mx1 = fmax(mx1,X_31);
    mx1 = fmax(mx1,X_41);

    mx2 = fmax(X_12,X_22);
    mx2 = fmax(mx2,X_32);
    mx2 = fmax(mx2,X_42);

    mx3 = fmax(X_13,X_23);
    mx3 = fmax(mx3,X_33);
    mx3 = fmax(mx3,X_43);

    //find candidate grid points
    smn1 = convert_int(ceil((mn1+L1*0.5)/dx1));
    smn2 = convert_int(ceil((mn2+L2*0.5-dx2/2.0)/dx2));
    smn3 = convert_int(ceil((mn3+L3*0.5-dx3/2.0)/dx3));
    
    smx1 = convert_int(floor((mx1+L1*0.5)/dx1));
    smx2 = convert_int(floor((mx2+L2*0.5-dx2/2.0)/dx2));
    smx3 = convert_int(floor((mx3+L3*0.5-dx3/2.0)/dx3));
    
    //check whether candidate points lie inside triangle
    for (int k3 = smn3; k3 <= smx3; k3++) {
       for (int k2 = smn2; k2 <= smx2; k2++) {
          for (int k1 = smn1; k1 <= smx1; k1++) {
             gpt1 = -L1*0.5+k1*dx1;
             gpt2 = -L2*0.5+k2*dx2+dx2/2.0;
             gpt3 = -L3*0.5+k3*dx3+dx3/2.0;

             kk = (k3 & N3-1); 
             jj = (k2 & N2-1); 
             ii = (k1 & N1-1); 

             //find perp vectors to planes 
             //find vectors to dot against
             chk121 = X_21-X_11;
             chk122 = X_22-X_12;
             chk123 = X_23-X_13;
             chk231 = X_31-X_11;
             chk232 = X_32-X_12;
             chk233 = X_33-X_13;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_11;
             chk122 = gpt2 - X_12;
             chk123 = gpt3 - X_13;

             dot1 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_41-X_21;
             chk122 = X_42-X_22;
             chk123 = X_43-X_23;
             chk231 = X_31-X_21;
             chk232 = X_32-X_22;
             chk233 = X_33-X_23;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_21;
             chk122 = gpt2 - X_22;
             chk123 = gpt3 - X_23;

             dot2 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_41-X_31;
             chk122 = X_42-X_32;
             chk123 = X_43-X_33;
             chk231 = X_11-X_31;
             chk232 = X_12-X_32;
             chk233 = X_13-X_33;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_31;
             chk122 = gpt2 - X_32;
             chk123 = gpt3 - X_33;

             dot3 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_21-X_41;
             chk122 = X_22-X_42;
             chk123 = X_23-X_43;
             chk231 = X_11-X_41;
             chk232 = X_12-X_42;
             chk233 = X_13-X_43;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_41;
             chk122 = gpt2 - X_42;
             chk123 = gpt3 - X_43;

             dot4 = p121*chk121+p122*chk122+p123*chk123;

             if (dot1 >= 0 && dot2 >= 0 && dot3 >= 0 && dot4 >= 0) {
                rho_1[ii+N1*jj+N1*N2*kk] = 1.0/4.0*(Rho[TV_1[i]]+Rho[TV_2[i]]+Rho[TV_3[i]]+Rho[TV_4[i]]);  
                mu_1[ii+N1*jj+N1*N2*kk] = 1.0/4.0*(Mu[TV_1[i]]+Mu[TV_2[i]]+Mu[TV_3[i]]+Mu[TV_4[i]]);  
             }
          }
       }
    }
    //find candidate grid points
    smn1 = convert_int(ceil((mn1+L1*0.5-dx1/2.0)/dx1));
    smn2 = convert_int(ceil((mn2+L2*0.5)/dx2));
    smn3 = convert_int(ceil((mn3+L3*0.5-dx3/2.0)/dx3));
    
    smx1 = convert_int(floor((mx1+L1*0.5-dx1/2.0)/dx1));
    smx2 = convert_int(floor((mx2+L2*0.5)/dx2));
    smx3 = convert_int(floor((mx3+L3*0.5-dx3/2.0)/dx2));

    //check whether candidate points lie inside triangle
    for (int k3 = smn3; k3 <= smx3; k3++) {
       for (int k2 = smn2; k2 <= smx2; k2++) {
          for (int k1 = smn1; k1 <= smx1; k1++) {
             gpt1 = -L1*0.5+k1*dx1+dx1/2.0;
             gpt2 = -L2*0.5+k2*dx2;
             gpt3 = -L3*0.5+k3*dx3+dx3/2.0;

             kk = (k3 & N3-1); 
             jj = (k2 & N2-1); 
             ii = (k1 & N1-1); 

             //find perp vectors to planes 
             //find vectors to dot against
             chk121 = X_21-X_11;
             chk122 = X_22-X_12;
             chk123 = X_23-X_13;
             chk231 = X_31-X_11;
             chk232 = X_32-X_12;
             chk233 = X_33-X_13;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_11;
             chk122 = gpt2 - X_12;
             chk123 = gpt3 - X_13;

             dot1 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_41-X_21;
             chk122 = X_42-X_22;
             chk123 = X_43-X_23;
             chk231 = X_31-X_21;
             chk232 = X_32-X_22;
             chk233 = X_33-X_23;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_21;
             chk122 = gpt2 - X_22;
             chk123 = gpt3 - X_23;

             dot2 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_41-X_31;
             chk122 = X_42-X_32;
             chk123 = X_43-X_33;
             chk231 = X_11-X_31;
             chk232 = X_12-X_32;
             chk233 = X_13-X_33;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_31;
             chk122 = gpt2 - X_32;
             chk123 = gpt3 - X_33;

             dot3 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_21-X_41;
             chk122 = X_22-X_42;
             chk123 = X_23-X_43;
             chk231 = X_11-X_41;
             chk232 = X_12-X_42;
             chk233 = X_13-X_43;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_41;
             chk122 = gpt2 - X_42;
             chk123 = gpt3 - X_43;

             dot4 = p121*chk121+p122*chk122+p123*chk123;

             if (dot1 >= 0 && dot2 >= 0 && dot3 >= 0 && dot4 >= 0) {
                rho_2[ii+N1*jj+N1*N2*kk] = 1.0/4.0*(Rho[TV_1[i]]+Rho[TV_2[i]]+Rho[TV_3[i]]+Rho[TV_4[i]]);  
                mu_2[ii+N1*jj+N1*N2*kk] = 1.0/4.0*(Mu[TV_1[i]]+Mu[TV_2[i]]+Mu[TV_3[i]]+Mu[TV_4[i]]);  
             }
          }
       }
    }

    //find candidate grid points
    smn1 = convert_int(ceil((mn1+L1*0.5-dx1/2.0)/dx1));
    smn2 = convert_int(ceil((mn2+L2*0.5-dx2/2.0)/dx2));
    smn3 = convert_int(ceil((mn3+L3*0.5)/dx3));
    
    smx1 = convert_int(floor((mx1+L1*0.5-dx1/2.0)/dx1));
    smx2 = convert_int(floor((mx2+L2*0.5-dx2/2.0)/dx2));
    smx3 = convert_int(floor((mx3+L3*0.5)/dx3));

    //check whether candidate points lie inside triangle
    for (int k3 = smn3; k3 <= smx3; k3++) {
       for (int k2 = smn2; k2 <= smx2; k2++) {
          for (int k1 = smn1; k1 <= smx1; k1++) {
             gpt1 = -L1*0.5+k1*dx1+dx1/2.0;
             gpt2 = -L2*0.5+k2*dx2+dx2/2.0;
             gpt3 = -L3*0.5+k3*dx3;

             kk = (k3 & N3-1); 
             jj = (k2 & N2-1); 
             ii = (k1 & N1-1); 

             //find perp vectors to planes 
             //find vectors to dot against
             chk121 = X_21-X_11;
             chk122 = X_22-X_12;
             chk123 = X_23-X_13;
             chk231 = X_31-X_11;
             chk232 = X_32-X_12;
             chk233 = X_33-X_13;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_11;
             chk122 = gpt2 - X_12;
             chk123 = gpt3 - X_13;

             dot1 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_41-X_21;
             chk122 = X_42-X_22;
             chk123 = X_43-X_23;
             chk231 = X_31-X_21;
             chk232 = X_32-X_22;
             chk233 = X_33-X_23;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_21;
             chk122 = gpt2 - X_22;
             chk123 = gpt3 - X_23;

             dot2 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_41-X_31;
             chk122 = X_42-X_32;
             chk123 = X_43-X_33;
             chk231 = X_11-X_31;
             chk232 = X_12-X_32;
             chk233 = X_13-X_33;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_31;
             chk122 = gpt2 - X_32;
             chk123 = gpt3 - X_33;

             dot3 = p121*chk121+p122*chk122+p123*chk123;

             chk121 = X_21-X_41;
             chk122 = X_22-X_42;
             chk123 = X_23-X_43;
             chk231 = X_11-X_41;
             chk232 = X_12-X_42;
             chk233 = X_13-X_43;

             p121 = chk122*chk233-chk123*chk232; 
             p122 = -(chk121*chk233-chk123*chk231); 
             p123 = chk121*chk232-chk122*chk231; 

             chk121 = gpt1 - X_41;
             chk122 = gpt2 - X_42;
             chk123 = gpt3 - X_43;

             dot4 = p121*chk121+p122*chk122+p123*chk123;

             if (dot1 >= 0 && dot2 >= 0 && dot3 >= 0 && dot4 >= 0) {
                rho_3[ii+N1*jj+N1*N2*kk] = 1.0/4.0*(Rho[TV_1[i]]+Rho[TV_2[i]]+Rho[TV_3[i]]+Rho[TV_4[i]]);  
                mu_3[ii+N1*jj+N1*N2*kk] = 1.0/4.0*(Mu[TV_1[i]]+Mu[TV_2[i]]+Mu[TV_3[i]]+Mu[TV_4[i]]);  
             }
          }
       }
    }
    }
    __kernel void calc_rho(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const unsigned *TV_4, __global const float *Rho, __global float *en)
    {
    unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;
    float X_41, X_42, X_43;

    float a1, a2, a3, b1, b2, b3;
    float n1, n2, n3, vol;

    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    X_41 = X_1[TV_4[i]];
    X_42 = X_2[TV_4[i]];
    X_43 = X_3[TV_4[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    a1 = X_41-X_11;
    a2 = X_42-X_12;
    a3 = X_43-X_13;

    vol = n1*a1+n2*a2+n3*a3;

    en[i] = 1.0/6.0*vol*1.0/4.0*(Rho[TV_1[i]]+Rho[TV_2[i]]+Rho[TV_3[i]]+Rho[TV_4[i]]);
    }
    __kernel void check_tet(__global const float *X_1, __global const float *X_2, __global const float *X_3, __global const unsigned *TV_1, __global const unsigned *TV_2, __global const unsigned *TV_3, __global const unsigned *TV_4, __global float *en)
    {
    unsigned i = get_global_id(0);

    float X_11, X_12, X_13;
    float X_21, X_22, X_23;
    float X_31, X_32, X_33;
    float X_41, X_42, X_43;

    float a1, a2, a3, b1, b2, b3;
    float n1, n2, n3, vol;

    X_11 = X_1[TV_1[i]];
    X_12 = X_2[TV_1[i]];
    X_13 = X_3[TV_1[i]];

    X_21 = X_1[TV_2[i]];
    X_22 = X_2[TV_2[i]];
    X_23 = X_3[TV_2[i]];

    X_31 = X_1[TV_3[i]];
    X_32 = X_2[TV_3[i]];
    X_33 = X_3[TV_3[i]];

    X_41 = X_1[TV_4[i]];
    X_42 = X_2[TV_4[i]];
    X_43 = X_3[TV_4[i]];

    a1 = X_21-X_11;
    a2 = X_22-X_12;
    a3 = X_23-X_13;

    b1 = X_31-X_11;
    b2 = X_32-X_12;
    b3 = X_33-X_13;

    n1 = a2*b3-a3*b2;
    n2 = a3*b1-a1*b3;
    n3 = a1*b2-a2*b1;

    a1 = X_41-X_11;
    a2 = X_42-X_12;
    a3 = X_43-X_13;

    vol = n1*a1+n2*a2+n3*a3;

    if (vol < 0.0) {
    en[0] = 1.0;
    }
    }
    """).build()
calc_lagF_wlc_new_kernel = ib_prg.calc_lagF_wlc_new
calc_lagF_wlc_new_kernel.set_scalar_arg_dtypes([None]*4 + [np.uint32]*2 + [np.float32]*2 + [None]*3)

calc_lagF_wlc_kernel = ib_prg.calc_lagF_wlc
calc_lagF_wlc_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*2 + [np.float32]*2 + [None]*3)

calc_lagF_spec_kernel = ib_prg.calc_lagF_spec
calc_lagF_spec_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*2 + [np.float32] + [None]*3)

calc_lagF_spec_new_kernel = ib_prg.calc_lagF_spec_new
calc_lagF_spec_new_kernel.set_scalar_arg_dtypes([None]*4 + [np.uint32]*2 + [np.float32] + [None]*3)

break_spec_kernel = ib_prg.break_spec
break_spec_kernel.set_scalar_arg_dtypes([None] + [np.float32]*2 + [None] + [np.uint32]*2)

symm_break_spec_kernel = ib_prg.symm_break_spec
symm_break_spec_kernel.set_scalar_arg_dtypes([None]*2  + [np.uint32]*2)

symm_make_spec_new_kernel = ib_prg.symm_make_spec_new
symm_make_spec_new_kernel.set_scalar_arg_dtypes([None]*3  + [np.uint32])

symm_make_spec_kernel = ib_prg.symm_make_spec
symm_make_spec_kernel.set_scalar_arg_dtypes([None]*2  + [np.uint32]*2)

symm_test_kernel = ib_prg.symm_test
symm_test_kernel.set_scalar_arg_dtypes([None]*2  + [np.uint32]*2)

make_spec_new_kernel = ib_prg.make_spec_new
make_spec_new_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*2 + [np.float32]*3 + [None]*2 + [np.uint32]*2)

make_spec_kernel = ib_prg.make_spec
make_spec_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*2 + [np.float32]*3 + [None] + [np.uint32]*3)

monitor_kernel = ib_prg.monitor_spec
monitor_kernel.set_scalar_arg_dtypes([None] + [np.uint32] + [None])

fill_make_distr_kernel = ib_prg.fill_make_distr
fill_make_distr_kernel.set_scalar_arg_dtypes([None]*5  + [np.uint32]*4 + [np.float32]*4 + [None]*2 + [np.uint32])

fill_make_new_kernel = ib_prg.fill_make_new
fill_make_new_kernel.set_scalar_arg_dtypes([None]*5  + [np.uint32]*4 + [np.float32]*4 + [None]*3 + [np.uint32]*2)

fill_make_kernel = ib_prg.fill_make
fill_make_kernel.set_scalar_arg_dtypes([None]*5  + [np.uint32]*4 + [np.float32]*4 + [None]*2 + [np.uint32]*3)

count_make_distr_kernel = ib_prg.count_make_distr
count_make_distr_kernel.set_scalar_arg_dtypes([None]*5  + [np.uint32]*4 + [np.float32]*4 + [None] + [np.uint32])

count_make_kernel = ib_prg.count_make
count_make_kernel.set_scalar_arg_dtypes([None]*5  + [np.uint32]*4 + [np.float32]*4 + [None]*2 + [np.uint32]*2)

proj_tri_kernel = ib_prg.proj_tri
proj_tri_kernel.set_scalar_arg_dtypes([None]*7 + [np.uint32] + [None]*3)

proj_sphere_kernel = ib_prg.proj_sphere
proj_sphere_kernel.set_scalar_arg_dtypes([None]*3 + [np.uint32] + [None]*3)

calc_nrml_kernel = ib_prg.calc_nrml
calc_nrml_kernel.set_scalar_arg_dtypes([None]*8 + [np.uint32] + [np.float32]*1 + [None]*3 + [np.uint32])

calc_lagF_area_kernel = ib_prg.calc_lagF_area
calc_lagF_area_kernel.set_scalar_arg_dtypes([None]*8 + [np.uint32] + [np.float32]*1 + [None]*3)

calc_lagF_hook_kernel = ib_prg.calc_lagF_hook
calc_lagF_hook_kernel.set_scalar_arg_dtypes([None]*10 + [np.uint32]*1 + [np.float32]*2 + [None]*3)

calc_energy_hook_kernel = ib_prg.calc_energy_hook
calc_energy_hook_kernel.set_scalar_arg_dtypes([None]*9 + [np.float32]*2 + [np.uint32] + [None])

calc_energy_area_kernel = ib_prg.calc_energy_area
calc_energy_area_kernel.set_scalar_arg_dtypes([None]*7 + [np.float32]*1 + [np.uint32] + [None])

calc_change_area_kernel = ib_prg.calc_change_area
calc_change_area_kernel.set_scalar_arg_dtypes([None]*7 + [np.float32]*1 + [np.uint32] + [None])

calc_total_area_kernel = ib_prg.calc_total_area
calc_total_area_kernel.set_scalar_arg_dtypes([None]*7 + [np.float32]*1 + [np.uint32] + [None])

calc_energy_volume_kernel = ib_prg.calc_energy_volume
calc_energy_volume_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32] + [None])

calc_energy_curv_kernel = ib_prg.calc_energy_curv
calc_energy_curv_kernel.set_scalar_arg_dtypes([None]*7 + [np.uint32]*2 + [np.float32] + [None])

calc_lagF_curv_kernel = ib_prg.calc_lagF_curv
calc_lagF_curv_kernel.set_scalar_arg_dtypes([None]*7 + [np.uint32]*1 + [np.float32] + [None]*3)

div_kernel = prg.div
div_kernel.set_scalar_arg_dtypes([None]*3 + [np.float32]*3 + [np.uint32]*3 + [None])

L_adj_1_kernel = prg.L_adj_1
L_adj_1_kernel.set_scalar_arg_dtypes([None])

L_adj_2_kernel = prg.L_adj_2
L_adj_2_kernel.set_scalar_arg_dtypes([None])

p_filt_kernel = prg.p_filt
p_filt_kernel.set_scalar_arg_dtypes([None])

nyq_filt_kernel = prg.nyq_filt
nyq_filt_kernel.set_scalar_arg_dtypes([None] + [np.uint32]*3)

solve_kernel = solve_prg.solve
solve_kernel.set_scalar_arg_dtypes([None]*7 + [np.float32]*4 + [np.uint32]*3 + [None]*3)

test_meml_kernel = solve_prg.test_meml
test_meml_kernel.set_scalar_arg_dtypes([None] +  [np.uint32]*3)

vc_laplace_kernel = solve_prg.vc_laplace
vc_laplace_kernel.set_scalar_arg_dtypes([None]*6 + [np.float32]*3 + [np.uint32]*3 + [None]*3)

dal_term_kernel = solve_prg.dal_term
dal_term_kernel.set_scalar_arg_dtypes([None]*12 + [np.float32] + [np.uint32]*3 + [None]*3)

grad_kernel = prg.grad
grad_kernel.set_scalar_arg_dtypes([None]*1 + [np.float32]*3 + [np.uint32]*3 + [None]*3)

ss_conv_kernel = prg.ss_conv
ss_conv_kernel.set_scalar_arg_dtypes([None]*3 + [np.float32]*3 + [np.uint32]*3 + [None]*3)

ss_conv_fast_kernel = prg.ss_conv_fast
ss_conv_fast_kernel.set_scalar_arg_dtypes([None]*3 + [np.float32]*3 + [np.uint32]*3 + [None]*3)

interp_kernel = ib_prg.interp
interp_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*3 + [ np.float32]*3 + [None]*3)
spread_pre_kernel = ib_prg.spread_pre
spread_pre_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*3 + [np.float32]*4 + [None]*6)
spread_pre_serial_kernel = ib_prg.spread_pre_serial
spread_pre_serial_kernel.set_scalar_arg_dtypes([None]*6 + [np.uint32]*4 + [np.float32]*4 + [None]*6)
spread_kernel = ib_prg.spread
spread_kernel.set_scalar_arg_dtypes([None]*12 + [np.uint32]*3 + [np.float32]*4 + [np.uint32]*3 + [None]*3)
spread_pre_col_kernel = ib_prg.spread_pre_col
spread_pre_col_kernel.set_scalar_arg_dtypes([None]*12 + [np.uint32]*3 + [np.float32]*4 + [None]*3)
spread_simple_col_kernel = ib_prg.spread_simple_col
spread_simple_col_kernel.set_scalar_arg_dtypes([None]*12 + [np.uint32]*3 + [np.float32]*4 + [np.uint32]*2 + [None]*3)
spread_col_kernel = ib_prg.spread_col
spread_col_kernel.set_scalar_arg_dtypes([None]*12 + [np.uint32]*3 + [np.float32]*4 + [np.uint32]*2 + [None]*3)
sum_col_kernel = ib_prg.sum_col
sum_col_kernel.set_scalar_arg_dtypes([None]*3 + [np.uint32]*3 + [None]*3)
spread_simple_kernel = ib_prg.spread_simple
spread_simple_kernel.set_scalar_arg_dtypes([None]*12 + [np.uint32]*3 + [np.float32]*4 + [np.uint32]*3 + [None]*3)
spread_serial_kernel = ib_prg.spread_serial
spread_serial_kernel.set_scalar_arg_dtypes([None]*12 + [np.uint32]*3 + [np.float32]*4 + [np.uint32]*3 + [None]*3)
updaten_spec_kernel = ib_prg.updaten_spec
updaten_spec_kernel.set_scalar_arg_dtypes([None]*5 + [np.uint32]*4 + [np.float32]*3 + [np.uint32]*3)
updaten_kernel = ib_prg.updaten
updaten_kernel.set_scalar_arg_dtypes([None]*9 + [np.uint32]*3 + [np.float32]*3 + [np.uint32]*3)
updaten_col_kernel = ib_prg.updaten_col
updaten_col_kernel.set_scalar_arg_dtypes([None]*8 + [np.uint32]*2 + [np.float32]*2 + [np.uint32]*2)

calc_coefs_kernel = ib_prg.calc_coefs
calc_coefs_kernel.set_scalar_arg_dtypes([None]*9 + [np.float32]*3 + [np.uint32]*3 + [None]*6)

calc_rho_kernel = ib_prg.calc_rho
calc_rho_kernel.set_scalar_arg_dtypes([None]*9)

check_tet_kernel = ib_prg.check_tet
check_tet_kernel.set_scalar_arg_dtypes([None]*8)

for ii in range(start_size,end_size+1): 
    #set up grid
    N1 = 2**ii1
    N2 = 2**ii2
    N3 = 2**ii3
    N1_in = N1
    N2_in = N2
    N3_in = N3
    N_sph = ii1
    num_rbc = 1
    dx1 = L1/N1
    dx2 = L2/N2
    dx3 = L3/N3
    
    rho_0 = 1.02
    #rho_0 = 0.03
    #rho_0 = 2.8*10**-8 

    x_stag = np.arange(-L1*0.5, L1*0.5, dx1)
    xx_1_stag = np.tile(x_stag, (N3, N2, 1))
    #xx_1_stag = np.tile(x_stag.reshape(N1,1,1), (1, N2, N3))
    x_stag = np.arange(-L2*0.5, L2*0.5, dx2)
    xx_2_stag = np.tile(x_stag.reshape(N2,1), (N3, 1, N1))
    #xx_2_stag = np.tile(x_stag.reshape(1,N2,1), (N1, 1, N3))
    x_stag = np.arange(-L3*0.5, L3*0.5, dx3)
    xx_3_stag = np.tile(x_stag.reshape(N3,1,1), (1, N2, N1))
    #xx_3_stag = np.tile(x_stag.reshape(1,1,N3), (N1, N2, 1))

    x_c = np.arange(-L1*0.5+dx1/2, L1*0.5+dx1/2, dx1)
    xx_1_c = np.tile(x_c, (N3, N2, 1))
    #xx_1_c = np.tile(x_c.reshape(N1,1,1), (1, N2, N3))
    x_c = np.arange(-L2*0.5+dx2/2, L2*0.5+dx2/2, dx2)
    xx_2_c = np.tile(x_c.reshape(N2,1), (N3, 1, N1))
    #xx_2_c = np.tile(x_c.reshape(1,N2,1), (N1, 1, N3))
    x_c = np.arange(-L3*0.5+dx3/2, L3*0.5+dx3/2, dx3)
    xx_3_c = np.tile(x_c.reshape(N3,1,1), (1, N2, N1))
    #xx_3_c = np.tile(x_c.reshape(1,1,N3), (N1, N2, 1))
    
    if PR_INT:
        mesh3 = np.vstack((xx_1_c[np.newaxis],xx_2_c[np.newaxis],xx_3_c[np.newaxis]))

    mu_0 = 0.012
    #mu_0 = 1.0/0.03 
    #mu_0 = 1.0
    #mu_0 = 0.36
    dt = 0.0075*dx3
    #dt = 0.005*dx3
    #dt = 0.01*dx3
    #dt = 0.01*dx3
    clock_max = np.int(np.round(20.0/dt,0))
    clock_max = 10000000
    #clock_max = 100
    #clock_max = 2
    print clock_max
    if INNIE:
        v_red = 0.41
        s_00 = 0.5*10**(-3)
        s_00 = 0.0

    #set up Lagrangian parameters
    rho_l = -rho_0+.1*rho_0
    mu_l = -mu_0+.1*mu_0
    mu_l = 0.0 
    rho_l = 0.0
    #mu_l = 4.0*mu_0
    #rho_l = 0.1*rho_0 
    grav = 0.0 
    #a_lag = 0.125 #start in circle
    #a_lag = 0.0625 #start in circle
    d_lag = L3*np.minimum(0.125, 1./(num_rbc*4.)) #start in circle
    a_lag = 0.75*L3 #start in circle
    #a_lag = L1*0.125
    #a_lag = 0.15*L1 #start in circle
    #a_lag = 0.3*L1 #start in circle

    CT_max = 6 #hack!
    #add sphere
    pkl_file = open('biconc.pkl', 'rb')
    picklelist = pickle.load(pkl_file)
    pkl_file.close()
    X_1 = picklelist[0]
    X_2 = picklelist[1]
    X_3 = picklelist[2]
    mn1 = np.mean(X_1)
    mn2 = np.mean(X_2)
    mn3 = np.mean(X_3)
    #X_1 = X_1-mn1
    #X_2 = X_2-mn2
    #X_3 = X_3-mn3
    TV_1 = picklelist[3][:,np.newaxis]
    TV_2 = picklelist[4][:,np.newaxis]
    TV_3 = picklelist[5][:,np.newaxis]
    X_ref_1 = picklelist[0]
    X_ref_2 = picklelist[1]
    X_ref_3 = picklelist[2]
    CT_one = picklelist[9]
    X_1_in = picklelist[10]-mn1
    X_2_in = picklelist[11]-mn2
    X_3_in = picklelist[12]-mn3
    X_1_orig = X_1.copy() 
    X_2_orig = X_2.copy() 
    X_3_orig = X_3.copy() 
    X_ref_1_orig = X_ref_1.copy() 
    X_ref_2_orig = X_ref_2.copy() 
    X_ref_3_orig = X_ref_3.copy() 
    if INNIE:
        pkl_file = open('ball.pkl', 'rb')
        picklelist = pickle.load(pkl_file)
        pkl_file.close()
        mya_lag = L1*1.15*0.32 #start in circle
        mya_lag = 0.9*(9/8.965)**(1./3.)*mya_lag
        X_1 = mya_lag*picklelist[0].copy()
        X_2 = mya_lag*picklelist[1].copy()
        X_3 = mya_lag*picklelist[2].copy()
        mn1 = np.mean(X_1)
        mn2 = np.mean(X_2)
        mn3 = np.mean(X_3)
        X_1 = X_1-mn1
        X_2 = X_2-mn2
        X_3 = X_3-mn3
        TV = picklelist[3]
        #TV_1 = TV[:,0][:,np.newaxis]
        #TV_2 = TV[:,1][:,np.newaxis]
        #TV_3 = TV[:,2][:,np.newaxis]
        X_ref_1 = mya_lag*picklelist[0].copy()
        X_ref_2 = mya_lag*picklelist[1].copy()
        X_ref_3 = mya_lag*picklelist[2].copy()
        pkl_file = open('ballch7.pkl', 'rb')
        picklelist = pickle.load(pkl_file)
        pkl_file.close()
        mya_lag = L1*1.15*0.32 #start in circle
        mya_lag = 0.9*(9/8.965)**(1./3.)*mya_lag
        fX = mya_lag*np.hstack((picklelist[0],picklelist[1],picklelist[2]))
        start_time = time.time()
        TV = picklelist[3]
        TV_spec = TV.copy()
        TV_spec_1_gpu = cl_array.to_device(queue, TV_spec[:,0].astype(np.uint32))
        TV_spec_2_gpu = cl_array.to_device(queue, TV_spec[:,1].astype(np.uint32))
        TV_spec_3_gpu = cl_array.to_device(queue, TV_spec[:,2].astype(np.uint32))
        CT = picklelist[4]
        CT_spec = CT.copy()
        CT_spec_gpu = cl_array.to_device(queue, CT_spec.astype(np.int32)) 
        szT = TV.shape[0]
        N_spec = CT.shape[0]
        if (np.mod(szT,2) == 1):
            print 'ball edge bug'
            sys.exit()
        szE = szT*3/2 
        fe = np.zeros((szE,2))
        ne = np.zeros((N_spec,1))
        eind = 0
        for ii in range(0,N_spec):
            for jj in range(0,CT_max):
                if (CT[ii,jj] != -1):
                    for kk in range(0,3):
                        if (ii < TV[CT[ii,jj],kk] and TV[CT[ii,jj],np.mod(kk+1,3)] == ii):
                            fe[eind,0] = ii 
                            fe[eind,1] = TV[CT[ii,jj],kk] 
                            ne[ii] += 1
                            ne[TV[CT[ii,jj],kk]] += 1
                            eind += 1
        print 'time spent making fe from ball', time.time()-start_time, 'seconds'
        #fnameX = '/home/tgf220/my-3d-code/mytestX6.txt'
        #fnamee = '/home/tgf220/my-3d-code/myteste6.txt'
        #fX = np.genfromtxt(fnameX,dtype=np.float32);
        #fe = np.genfromtxt(fnamee,dtype=np.uint32);
        #fe = fe-1
        N_spec = fX.shape[0]
    else:
        #fnameX = '/home/tfai/mytestX4.txt'
        #fnamee = '/home/tfai/myteste4.txt'
        fnameX = '/home/tgf220/my-3d-code/mytestX4.txt'
        fnamee = '/home/tgf220/my-3d-code/myteste4.txt'
        fX = np.genfromtxt(fnameX,dtype=np.float32);
        fe = np.genfromtxt(fnamee,dtype=np.uint32);
        fe = fe-1
        N_spec = fX.shape[0]
        #identify triangles
        tri_ind = np.zeros((N_spec,1)) 
        j_tri = 0
        start_time = time.time()
        for i in range(0,N_spec):
            x1 = fX[i,0]
            x2 = fX[i,1]
            x3 = fX[i,2]

            x11 = X_1[TV_1[j_tri]]
            x12 = X_2[TV_1[j_tri]]
            x13 = X_3[TV_1[j_tri]]
            
            x21 = X_1[TV_2[j_tri]]
            x22 = X_2[TV_2[j_tri]]
            x23 = X_3[TV_2[j_tri]]
            
            x31 = X_1[TV_3[j_tri]]
            x32 = X_2[TV_3[j_tri]]
            x33 = X_3[TV_3[j_tri]]
            
            #find normal
            a1 = x21-x11 
            a2 = x22-x12 
            a3 = x23-x13 

            b1 = x31-x11 
            b2 = x32-x12 
            b3 = x33-x13 

            n1 = a2*b3-a3*b2
            n2 = -(a1*b3-a3*b1)
            n3 = a1*b2-a2*b1

            norm = np.sqrt(n1*n1+n2*n2+n3*n3)
            n1 = n1/norm
            n2 = n2/norm
            n3 = n3/norm

            a1 = x21-x11 
            a2 = x22-x12 
            a3 = x23-x13 

            m1 = n2*a3-n3*a2
            m2 = -(n1*a3-n3*a1)
            m3 = n1*a2-n2*a1

            norm = np.sqrt(m1*m1+m2*m2+m3*m3)
            m1 = m1/norm
            m2 = m2/norm
            m3 = m3/norm

            b1 = x1-x11
            b2 = x2-x12
            b3 = x3-x13

            norm = np.sqrt(b1*b1+b2*b2+b3*b3)
            b1 = b1/norm
            b2 = b2/norm
            b3 = b3/norm

            dot1 = m1*b1+m2*b2+m3*b3

            a1 = x31-x21 
            a2 = x32-x22 
            a3 = x33-x23 

            m1 = n2*a3-n3*a2
            m2 = -(n1*a3-n3*a1)
            m3 = n1*a2-n2*a1

            norm = np.sqrt(m1*m1+m2*m2+m3*m3)
            m1 = m1/norm
            m2 = m2/norm
            m3 = m3/norm

            b1 = x1-x21
            b2 = x2-x22
            b3 = x3-x23

            norm = np.sqrt(b1*b1+b2*b2+b3*b3)
            b1 = b1/norm
            b2 = b2/norm
            b3 = b3/norm

            dot2 = m1*b1+m2*b2+m3*b3

            a1 = x11-x31 
            a2 = x12-x32 
            a3 = x13-x33 

            m1 = n2*a3-n3*a2
            m2 = -(n1*a3-n3*a1)
            m3 = n1*a2-n2*a1

            norm = np.sqrt(m1*m1+m2*m2+m3*m3)
            m1 = m1/norm
            m2 = m2/norm
            m3 = m3/norm

            b1 = x1-x31
            b2 = x2-x32
            b3 = x3-x33

            norm = np.sqrt(b1*b1+b2*b2+b3*b3)
            b1 = b1/norm
            b2 = b2/norm
            b3 = b3/norm

            dot3 = m1*b1+m2*b2+m3*b3

            while(dot1 < 0 or dot2 < 0 or dot3 < 0):
                j_tri = j_tri+1

                #is i in j_tri?
                x11 = X_1[TV_1[j_tri]]
                x12 = X_2[TV_1[j_tri]]
                x13 = X_3[TV_1[j_tri]]
                
                x21 = X_1[TV_2[j_tri]]
                x22 = X_2[TV_2[j_tri]]
                x23 = X_3[TV_2[j_tri]]
                
                x31 = X_1[TV_3[j_tri]]
                x32 = X_2[TV_3[j_tri]]
                x33 = X_3[TV_3[j_tri]]
                
                #find normal
                a1 = x21-x11 
                a2 = x22-x12 
                a3 = x23-x13 

                b1 = x31-x11 
                b2 = x32-x12 
                b3 = x33-x13 

                n1 = a2*b3-a3*b2
                n2 = -(a1*b3-a3*b1)
                n3 = a1*b2-a2*b1

                norm = np.sqrt(n1*n1+n2*n2+n3*n3)
                n1 = n1/norm
                n2 = n2/norm
                n3 = n3/norm

                a1 = x21-x11 
                a2 = x22-x12 
                a3 = x23-x13 

                m1 = n2*a3-n3*a2
                m2 = -(n1*a3-n3*a1)
                m3 = n1*a2-n2*a1

                norm = np.sqrt(m1*m1+m2*m2+m3*m3)
                m1 = m1/norm
                m2 = m2/norm
                m3 = m3/norm

                b1 = x1-x11
                b2 = x2-x12
                b3 = x3-x13

                norm = np.sqrt(b1*b1+b2*b2+b3*b3)
                b1 = b1/norm
                b2 = b2/norm
                b3 = b3/norm

                dot1 = m1*b1+m2*b2+m3*b3

                a1 = x31-x21 
                a2 = x32-x22 
                a3 = x33-x23 

                m1 = n2*a3-n3*a2
                m2 = -(n1*a3-n3*a1)
                m3 = n1*a2-n2*a1

                norm = np.sqrt(m1*m1+m2*m2+m3*m3)
                m1 = m1/norm
                m2 = m2/norm
                m3 = m3/norm

                b1 = x1-x21
                b2 = x2-x22
                b3 = x3-x23

                norm = np.sqrt(b1*b1+b2*b2+b3*b3)
                b1 = b1/norm
                b2 = b2/norm
                b3 = b3/norm

                dot2 = m1*b1+m2*b2+m3*b3

                a1 = x11-x31 
                a2 = x12-x32 
                a3 = x13-x33 

                m1 = n2*a3-n3*a2
                m2 = -(n1*a3-n3*a1)
                m3 = n1*a2-n2*a1

                norm = np.sqrt(m1*m1+m2*m2+m3*m3)
                m1 = m1/norm
                m2 = m2/norm
                m3 = m3/norm

                b1 = x1-x31
                b2 = x2-x32
                b3 = x3-x33

                norm = np.sqrt(b1*b1+b2*b2+b3*b3)
                b1 = b1/norm
                b2 = b2/norm
                b3 = b3/norm

                dot3 = m1*b1+m2*b2+m3*b3

            tri_ind[i] = j_tri  

    print 'time spent finding triangles', time.time()-start_time, 'seconds'

    TV = np.hstack((TV_1,TV_2,TV_3))
    print TV.shape
    szT = TV_1.shape[0]
    N_r = X_1.shape[0]

    #include for area force
    k_area = 0.1*(1.0/0.77975)*(1.0/1.318)*(1.0/2.10495239) 
    k_area = 0.3 
    N_tri = szT 
    A_0 = np.zeros((szT,1))  
    for i in range(0,szT):
        x11 = X_ref_1[TV[i,0]]
        x12 = X_ref_2[TV[i,0]]
        x13 = X_ref_3[TV[i,0]]
        x21 = X_ref_1[TV[i,1]]
        x22 = X_ref_2[TV[i,1]]
        x23 = X_ref_3[TV[i,1]]
        x31 = X_ref_1[TV[i,2]]
        x32 = X_ref_2[TV[i,2]]
        x33 = X_ref_3[TV[i,2]]
        b1 = x31-x11
        b2 = x32-x12
        b3 = x33-x13
        a1 = x21-x11
        a2 = x22-x12
        a3 = x23-x13
        n1 = a2*b3-a3*b2
        n2 = a3*b1-a1*b3
        n3 = a1*b2-a2*b1
        A_0[i] = 0.5*np.sqrt(n1*n1+n2*n2+n3*n3)

    TV = TV[np.nonzero(A_0 != 0.0)[0],:]
    temp = int(sum(A_0 == 0.0)[0])
    N_tri = N_tri - temp 
    A_0 = A_0[A_0 != 0.0]
    da = np.mean(A_0)
    ##reduced volume
    #A_0 = 1.00*A_0 

    #neo-Hookean parameters
    k_bulk = 0.3*0.1
    k_shear = 0.3*2.5*10**-6
    #k_bulk = 0.1
    k_bulk = 0.1
    k_bulk = 0.01
    k_bulk = 1.0
    #k_bulk = 0.75
    #k_bulk = 0.4
    #k_shear = 5.0*10**-3
    k_shear = 2.5*10**-3
    #k_bulk = 0.0
    k_shear = 0.0

    for i in range(0,num_rbc-1):
        X_1 = np.vstack((X_1, X_1_orig))
        X_2 = np.vstack((X_2, X_2_orig))
        X_3 = np.vstack((X_3, X_3_orig+4.*d_lag*(i+1)))
        X_ref_1 = np.vstack((X_ref_1, X_ref_1_orig))
        X_ref_2 = np.vstack((X_ref_2, X_ref_2_orig))
        X_ref_3 = np.vstack((X_ref_3, X_ref_3_orig))

    TV_orig = TV.copy()
    A_0_orig = A_0.copy()
    for i in range(0,num_rbc-1):
        TV = np.vstack((TV, TV_orig+N_r*(i+1)))
        A_0 = np.vstack((A_0, A_0_orig))

    N_r_one = N_r
    N_tri_one = N_tri
    N_r = (TV.shape[0]/N_tri)*N_r 
    if (np.mod(N_r, 8) == 0):
        b_WGPSIZE_1 = 8
    elif (np.mod(N_r, 4) == 0):
        b_WGPSIZE_1 = 4
    elif (np.mod(N_r, 2) == 0):
        b_WGPSIZE_1 = 2
    else:
        b_WGPSIZE_1 = 1

    TV_new = []
    for i in range(0,TV.shape[0]):
        TV_new.append((int(TV[i,0]),int(TV[i,1]),int(TV[i,2])))
    TW = np.zeros((3,4))
    N_tet = TW.shape[0]

    print 'N_spec is', N_spec
    Ne_spec = fe.shape[0]
    k_spec = 0.0016
    #k_spec = 0.0032
    L_cont = 0.00002
    L_p = 0.000002
    k_wlc = 2.0/3.0*k_spec*L_cont 
    X_1 = np.vstack((X_1, fX[:,0][:,np.newaxis])).copy()
    X_2 = np.vstack((X_2, fX[:,1][:,np.newaxis])).copy()
    X_3 = np.vstack((X_3, fX[:,2][:,np.newaxis])).copy()
    if (np.mod(N_spec, 8) == 0):
        b_WGPSIZE_4 = 8
    elif (np.mod(N_spec, 4) == 0):
        b_WGPSIZE_4 = 4
    elif (np.mod(N_spec, 2) == 0):
        b_WGPSIZE_4 = 2
    else:
        b_WGPSIZE_4 = 1

    #A_0 = np.zeros((N_tri,1))  
    #for i in range(0,N_tri):
    #    x11 = X_1[TV[i,0]]
    #    x12 = X_2[TV[i,0]]
    #    x13 = X_3[TV[i,0]]
    #    x21 = X_1[TV[i,1]]
    #    x22 = X_2[TV[i,1]]
    #    x23 = X_3[TV[i,1]]
    #    x31 = X_1[TV[i,2]]
    #    x32 = X_2[TV[i,2]]
    #    x33 = X_3[TV[i,2]]
    #    b1 = x31-x11
    #    b2 = x32-x12
    #    b3 = x33-x13
    #    a1 = x21-x11
    #    a2 = x22-x12
    #    a3 = x23-x13
    #    n1 = a2*b3-a3*b2
    #    n2 = a3*b1-a1*b3
    #    n3 = a1*b2-a2*b1
    #    A_0[i] = 0.5*np.sqrt(n1*n1+n2*n2+n3*n3)

    #include for mean curvature
    k_curv = 0.3*(0.003)**-2*2.2*10**-12
    k_curv = 2.0*10**-12
    #k_curv = 1.0*10**-11
    #k_curv = 0.0

    CT = CT_one.copy()

    nmo_0 = np.nonzero(CT_one != -1)[0]
    nmo_1 = np.nonzero(CT_one != -1)[1]
    for i in range(0,num_rbc-1):
        CT_ex = CT_one.copy()
        CT_ex[nmo_0, nmo_1] = CT_ex[nmo_0, nmo_1]+N_tri_one*(i+1)
        CT = np.vstack((CT, CT_ex)).copy()

    ne = np.zeros((N_spec, 1)).astype(np.int32)
    for i in range(0, Ne_spec):
        ne[fe[i,0]] += 1
        ne[fe[i,1]] += 1

    CE = -1.0*np.ones((N_spec,np.max(ne))).astype(np.int32)
    CE_max = np.max(ne).astype(np.uint32)
    ne = np.zeros((N_spec, 1)).astype(np.int32)
    for i in range(0, Ne_spec):
        CE[fe[i,0],ne[fe[i,0]]] = i
        CE[fe[i,1],ne[fe[i,1]]] = i
        ne[fe[i,0]] += 1
        ne[fe[i,1]] += 1

    CX_max = 60 #max number of connected vertices
    CX = -1.0*np.ones((N_spec,CX_max)).astype(np.int32)
    ne = np.zeros((N_spec, 1)).astype(np.int32)
    for i in range(0, Ne_spec):
        CX[fe[i,0],ne[fe[i,0]]] = fe[i,1]
        CX[fe[i,1],ne[fe[i,1]]] = fe[i,0]
        ne[fe[i,0]] += 1
        ne[fe[i,1]] += 1

    CX_el_max = 60
    CX_el = -1.0*np.ones((N_spec*CX_el_max)).astype(np.int32)
    #CX_el = -1.0*np.ones((N_spec,CX_el_max)).astype(np.int32)
    #CX_el_new = -1.0*np.ones((N_spec*CX_el_max)).astype(np.int32)

    #rands = np.ones((CX_el.shape))
    #rands[1,0] = 0;
    #rands_new = np.ones((CX_el_new.shape))
    #rands_new[34] = 0;

    tablesize = 10000
    int_const = 1.0/4.0*np.sqrt(np.pi*(2.0*L_cont*L_p/3.0)**3)
    mmu = 5.0
    mydens = N_spec/(1.38*10**-6)
    myfuntable = np.zeros((tablesize,1));
    for i in range(0,tablesize):
        x = L_cont*i/np.float32(tablesize)
        myfuntable[i] = x**2*np.exp(-3.0*x**2/(2.0*L_cont*L_p))/int_const*mmu/(2.0*np.pi)/mydens  

    kbrk = 100
    kbrk = 0 
    N_pre_spec = N_r 

    #for dynamic network
    #N1_spec = 32 #must be power of two for fancy mod math!!
    #N2_spec = 32
    #N3_spec = 64
    N1_spec = 48
    N2_spec = 48
    N3_spec = 96

    dx1_spec = L1/N1_spec #smallest size that divides domain by factor of 4 and is bigger than L_cont
    dx2_spec = L2/N2_spec
    dx3_spec = L3/N3_spec

    init_spec_fn(X_1, X_2, X_3, N_spec, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec)

    #init_fn(X_1, X_2, X_3, N_r, N1, N2, N3, dx1, dx2, dx3)
    init_fn(X_1, X_2, X_3, N_r+N_spec, N1, N2, N3, dx1, dx2, dx3)

    #init_col_fn(X_2, X_3, N_r, N2, N3, dx2, dx3)
    #init_col_fn(X_2, X_3, N_r+N_spec, N2, N3, dx2, dx3)

    N_vis = X_1_in.shape[0]
    N_vis = 0
    
    ##add density spreaders
    ##X_1_c = np.arange(-0.5+dx/2., 0.5+dx/2., dx)
    ##X_2_c = np.arange(-0.5+dx/2., 0.5+dx/2., dx)
    ##X_3_c = np.arange(-0.5+dx/2., 0.5+dx/2., dx)
    #dx1_in = L1/N1_in 
    #dx2_in = L2/N2_in 
    #dx3_in = L3/N3_in 
    #X_1_c = np.arange(-L1*0.5+dx1_in/2., L1*0.5+dx1_in/2., dx1_in)
    #X_2_c = np.arange(-L2*0.5+dx2_in/2., L2*0.5+dx2_in/2., dx2_in)
    #X_3_c = np.arange(-L3*0.5+dx3_in/2., L3*0.5+dx3_in/2., dx3_in)
    #XX_1_c, XX_2_c, XX_3_c = meshgrid2(X_1_c, X_2_c, X_3_c)
    ##X_1 = np.vstack((X_1,XX_1_c[(XX_1_c**2+XX_2_c**2+XX_3_c**2)<a_lag**2][:,np.newaxis]))
    ##X_2 = np.vstack((X_2,XX_2_c[(XX_1_c**2+XX_2_c**2+XX_3_c**2)<a_lag**2][:,np.newaxis]))
    ##X_3 = np.vstack((X_3,XX_3_c[(XX_1_c**2+XX_2_c**2+XX_3_c**2)<a_lag**2][:,np.newaxis]))

    #X_1_in = XX_1_c[(XX_1_c**2+XX_2_c**2+XX_3_c**2)<a_lag**2][:,np.newaxis]
    #X_2_in = XX_2_c[(XX_1_c**2+XX_2_c**2+XX_3_c**2)<a_lag**2][:,np.newaxis]
    #X_3_in = XX_3_c[(XX_1_c**2+XX_2_c**2+XX_3_c**2)<a_lag**2][:,np.newaxis]
    ##X_1 = np.vstack((X_1, X_1_in, X_1_in+3.0*a_lag)).copy()
    ##X_2 = np.vstack((X_2, X_2_in, X_2_in)).copy()
    ##X_3 = np.vstack((X_3, X_3_in, X_3_in)).copy()
    ##X_1 = np.vstack((X_1, X_1_in, X_1_in+3*a_lag, X_1_in-3*a_lag, X_1_in+6*a_lag, X_1_in-6*a_lag)).copy()

    #for i in range(0,num_rbc):
    #    X_1 = np.vstack((X_1, X_1_in))
    #    X_2 = np.vstack((X_2, X_2_in))
    #    X_3 = np.vstack((X_3, X_3_in+4.*d_lag*i))

    diff_q = 0
    b_q = X_1.shape[0]
    if (np.mod(b_q, 8) == 0):
        b_WGPSIZE_2 = 8
    elif (np.mod(b_q, 4) == 0):
        b_WGPSIZE_2 = 4
    elif (np.mod(b_q, 2) == 0):
        b_WGPSIZE_2 = 2
    else:
        b_WGPSIZE_2 = 1
    b_q_orig = b_q
    N_tri = TV.shape[0]

    #include for shear force
    body = np.zeros((N3,N2,N1))
    body[:,:,0] = -1.0
    body[:,:,1] = 1.0
    gamma = 2.5 
    gamma = 0.0 
    body_f = 2.*2./3.*12*mu_0*a_lag*gamma/(dx3*L1*L2)

    print 'b_q is', b_q
    #print '64*(N_r) is', 64*(N_r)
    print '64*(N_r + N_spec) is', 64*(N_r+N_spec)
    print 'number of triangles is', TV.shape[0]

    print 'number of tetrahedra is', N_tet

    Rho = np.hstack((rho_l*np.ones((b_q))))  
    Mu = np.hstack((mu_l*np.ones((b_q))))  
    dtheta = dx1*dx2*dx3
    dtheta = 1.0 
    print 'da', da

    #debugging
    mu_1 = mu_0 * np.ones((N3,N2,N1))
    mu_2 = mu_0 * np.ones((N3,N2,N1))
    mu_3 = mu_0 * np.ones((N3,N2,N1))

    mu_min = mu_0
    mu_max = mu_0 + mu_l
    #mu_hat = 0.5*(mu_min+mu_max)
    mu_hat = mu_max
    rho_min = rho_0
    rho_max = rho_0 + rho_l
    rho_hat = 0.5*(rho_min+rho_max)
    #mu_bar = 0 
    #rho_bar = 0 
    #mu_bar = 5.0*mu_0  
    #rho_bar = 0.05*rho_0 
    #print 'mu_bar is', mu_bar
    #print 'rho_bar is', rho_bar
    #mu_0 = mu_0+mu_bar
    #rho_0 = rho_0+rho_bar

    #move data to gpu

    L_tf = calc_transf(N1,N2,N3,dx1,dx2,dx3)

    #u_1_soln = 2*np.cos(2*pi/L1*xx_1_stag)*np.sin(4*pi/L2*xx_2_c)
    #u_2_soln = -np.sin(2*pi*xx_1_c)*np.cos(4*pi*xx_2_stag)
    #u_1_soln = -np.sin(2*pi*xx_2_c)*np.cos(2*pi*xx_1_stag)
    #u_2_soln = np.sin(2*pi*xx_1_c)*np.cos(2*pi*xx_2_stag)
    u_1_soln = np.zeros((N3,N2,N1)) #initial conditions
    u_2_soln = np.zeros((N3,N2,N1))
    u_3_soln = np.zeros((N3,N2,N1))
    #u_1_soln = 2*np.cos(2*pi/L1*xx_1_stag)*np.sin(4*pi/L2*xx_2_c)
    #u_2_soln = -np.sin(2*pi*xx_1_c)*np.cos(4*pi*xx_2_stag)
    #u_3_soln = np.ones((N3,N2,N1))
    #u_1_soln = np.random.rand(N3,N2,N1)
    #u_2_soln = np.random.rand(N3,N2,N1)
    #u_3_soln = np.random.rand(N3,N2,N1)
    u_1_flat = np.zeros((N1*N2*N3))
    #u_1_soln = np.zeros((N1,N2,N3)) #initial conditions
    #u_2_soln = np.zeros((N1,N2,N3))
    #u_3_soln = np.zeros((N1,N2,N3))
    #u_3_soln = np.cos(2*pi*xx_1_c)*np.sin(4*pi*xx_2_c)

    sort = RadixSort(ctx, "unsigned *aryind, float *aryamt", key_expr="aryind[i]",
            sort_arg_names=["aryind"]+["aryamt"])
    #pre_amt = np.zeros((64*(N_r)))
    pre_amt = np.zeros((64*(N_r+N_spec)))
    #pre_amt = np.ones((10))
    #pre_amt[0] = 100
    #pre_amt[9] = 1000
    #pre_ind = np.array([9, 9, 1, 9, 1, 3, 1, 1, 3, 3]).astype(np.uint32)
    #print pre_amt.shape

    #pre_amt = np.ones((4))
    #pre_ind = np.array([0, 0, 1, 1])
    #f_flat = np.array([0, 0])

    pre_col = np.zeros((N2,N1,N3,4,4))
    from pyopencl.scan import GenericScanKernel
    scan_knl = GenericScanKernel(
        ctx, np.float32,
        arguments="float *tgt_mesh, unsigned *sorted_tgt_indices, float *contribution",
        input_expr="contribution[i]",
        #scan_expr="a+b", neutral="0",
        scan_expr="across_seg_boundary ? b : a+b", neutral="0",
        is_segment_start_expr="(i == 0 || sorted_tgt_indices[i-1] != sorted_tgt_indices[i])",
        output_statement="""
                if (i+1 >= n || sorted_tgt_indices[i] != sorted_tgt_indices[i+1]) // ?
                        tgt_mesh[sorted_tgt_indices[i]] = item;""",
	preamble="""
	#define n (unsigned) 3258304 
	//#define n (unsigned) 10 
        """
        )
        #% dict(nscan=64)
        #//""" % dict(nscan=64*(N_r+N_spec))
        #)

    simple_scan_knl = GenericScanKernel(
        ctx, np.int32,
        arguments="__global int *ary",
        input_expr="ary[i]",
        scan_expr="a+b", neutral="0",
        output_statement="ary[i] = item;")

    #move data to gpu
    start_time = time.time()
    plan = Plan((N3, N2, N1), queue=queue)
    print 'time spent making plan is', time.time()-start_time, 'seconds'

    #rangen = RanluxGenerator(queue=queue, num_work_items=N_spec*CX_max, luxury=2, seed=None, max_work_items=N_spec*CX_max)
    rangen2 = RanluxGenerator(queue=queue, num_work_items=N_spec*CX_el_max, luxury=2, seed=None, max_work_items=N_spec*CX_el_max)
    rangen1 = RanluxGenerator(queue=queue, num_work_items=N_spec*CX_max, luxury=2, seed=None, max_work_items=N_spec*CX_el_max)
    print 'time spent initializing rng is', time.time()-start_time, 'seconds'

    u_1_gpu = cl_array.to_device(queue, u_1_soln.astype(np.float32))
    u_2_gpu = cl_array.to_device(queue, u_2_soln.astype(np.float32))
    u_3_gpu = cl_array.to_device(queue, u_3_soln.astype(np.float32))
    u_1_o_gpu = cl_array.to_device(queue, u_1_soln.astype(np.float32))
    u_2_o_gpu = cl_array.to_device(queue, u_2_soln.astype(np.float32))
    u_3_o_gpu = cl_array.to_device(queue, u_3_soln.astype(np.float32))
    u_1_tf_gpu = cl_array.to_device(queue, u_1_soln.astype(np.complex64))
    u_2_tf_gpu = cl_array.to_device(queue, u_2_soln.astype(np.complex64))
    u_3_tf_gpu = cl_array.to_device(queue, u_3_soln.astype(np.complex64))
    L_tf_gpu = cl_array.to_device(queue, L_tf.astype(np.complex64))
    u_1_flat = u_1_soln.flatten()
    f_1_flat_gpu = cl_array.to_device(queue, u_1_flat.astype(np.float32))
    f_2_flat_gpu = cl_array.to_device(queue, u_1_flat.astype(np.float32))
    f_3_flat_gpu = cl_array.to_device(queue, u_1_flat.astype(np.float32))
    #f_1_flat_gpu = cl_array.to_device(queue, pre_amt.astype(np.float32))
    #f_2_flat_gpu = cl_array.to_device(queue, pre_amt.astype(np.float32))
    #f_3_flat_gpu = cl_array.to_device(queue, pre_amt.astype(np.float32))
    f_1_gpu = cl_array.empty_like(u_1_gpu) 
    f_2_gpu = cl_array.empty_like(u_1_gpu) 
    f_3_gpu = cl_array.empty_like(u_1_gpu) 
    f_1_tf_gpu = cl_array.empty_like(u_1_tf_gpu) 
    f_2_tf_gpu = cl_array.empty_like(u_1_tf_gpu) 
    f_3_tf_gpu = cl_array.empty_like(u_1_tf_gpu) 
    p_gpu = cl_array.empty_like(u_1_gpu) 
    p_tf_gpu = cl_array.empty_like(u_1_tf_gpu) 
    u_1_tilde_gpu = cl_array.empty_like(u_1_gpu) 
    u_2_tilde_gpu = cl_array.empty_like(u_1_gpu) 
    u_3_tilde_gpu = cl_array.empty_like(u_1_gpu) 
    #firstn1_gpu = cl_array.to_device(queue, firstn1.astype(np.int32))
    #nextn1_gpu = cl_array.to_device(queue, nextn1.astype(np.int32))
    #firstn2_gpu = cl_array.to_device(queue, firstn2.astype(np.int32))
    #nextn2_gpu = cl_array.to_device(queue, nextn2.astype(np.int32))
    #firstn3_gpu = cl_array.to_device(queue, firstn3.astype(np.int32))
    #nextn3_gpu = cl_array.to_device(queue, nextn3.astype(np.int32))
    X_1_gpu = cl_array.to_device(queue, X_1.astype(np.float32))
    X_2_gpu = cl_array.to_device(queue, X_2.astype(np.float32))
    X_3_gpu = cl_array.to_device(queue, X_3.astype(np.float32))
    X_ref_1_gpu = cl_array.to_device(queue, X_ref_1.astype(np.float32))
    X_ref_2_gpu = cl_array.to_device(queue, X_ref_2.astype(np.float32))
    X_ref_3_gpu = cl_array.to_device(queue, X_ref_3.astype(np.float32))
    TV_gpu = cl_array.to_device(queue, TV.astype(np.int32))
    TV_1_gpu = cl_array.to_device(queue, TV[:,0].astype(np.uint32))
    TV_2_gpu = cl_array.to_device(queue, TV[:,1].astype(np.uint32))
    TV_3_gpu = cl_array.to_device(queue, TV[:,2].astype(np.uint32))
    TW_1_gpu = cl_array.to_device(queue, TW[:,0].astype(np.uint32))
    TW_2_gpu = cl_array.to_device(queue, TW[:,1].astype(np.uint32))
    TW_3_gpu = cl_array.to_device(queue, TW[:,2].astype(np.uint32))
    TW_4_gpu = cl_array.to_device(queue, TW[:,3].astype(np.uint32))
    X_1_tilde_gpu = cl_array.to_device(queue, X_1.astype(np.float32))
    X_2_tilde_gpu = cl_array.to_device(queue, X_2.astype(np.float32))
    X_3_tilde_gpu = cl_array.to_device(queue, X_3.astype(np.float32))
    F_1_gpu = cl_array.empty_like(X_1_gpu) 
    F_2_gpu = cl_array.empty_like(X_1_gpu) 
    F_3_gpu = cl_array.empty_like(X_1_gpu) 
    U_1_gpu = cl_array.empty_like(X_1_gpu) 
    U_2_gpu = cl_array.empty_like(X_1_gpu) 
    U_3_gpu = cl_array.empty_like(X_1_gpu) 
    A_0_gpu = cl_array.to_device(queue, A_0.astype(np.float32))
    A_ch_gpu = cl_array.empty_like(A_0_gpu) 
    tri_ind_gpu = cl_array.to_device(queue, tri_ind.astype(np.uint32)) 
    CT_gpu = cl_array.to_device(queue, CT.astype(np.int32)) 
    Rho_gpu = cl_array.to_device(queue, Rho.astype(np.float32)) 
    Mu_gpu = cl_array.to_device(queue, Mu.astype(np.float32)) 
    #mu_1_gpu = cl_array.empty_like(u_1_gpu) 
    #mu_2_gpu = cl_array.empty_like(u_1_gpu) 
    #mu_3_gpu = cl_array.empty_like(u_1_gpu) 
    rho_1_gpu = cl_array.empty_like(u_1_gpu) 
    rho_2_gpu = cl_array.empty_like(u_1_gpu) 
    rho_3_gpu = cl_array.empty_like(u_1_gpu) 
    body_gpu = cl_array.to_device(queue, body.astype(np.float32)) 

    ##for new spreading
    #precol_1 = cl_array.to_device(queue, pre_col.astype(np.float32))
    #precol_2 = cl_array.to_device(queue, pre_col.astype(np.float32))
    #precol_3 = cl_array.to_device(queue, pre_col.astype(np.float32))
    #preamt_1 = cl_array.to_device(queue, pre_amt.astype(np.float32))
    #preamt_2 = cl_array.to_device(queue, pre_amt.astype(np.float32))
    #preamt_3 = cl_array.to_device(queue, pre_amt.astype(np.float32))
    #preind_1 = cl_array.to_device(queue, pre_amt.astype(np.uint32))
    #preind_2 = cl_array.to_device(queue, pre_amt.astype(np.uint32))
    #preind_3 = cl_array.to_device(queue, pre_amt.astype(np.uint32))
    ##for debugging
    ##xx_1_stag = np.random.rand(4,4)
    #xx_1_stag_gpu = cl_array.to_device(queue, xx_1_stag.astype(np.float32))
    #xx_2_stag_gpu = cl_array.to_device(queue, xx_2_stag.astype(np.float32))
    #xx_3_stag_gpu = cl_array.to_device(queue, xx_3_stag.astype(np.float32))
    #xx_1_c_gpu = cl_array.to_device(queue, xx_1_c.astype(np.float32))
    #xx_2_c_gpu = cl_array.to_device(queue, xx_2_c.astype(np.float32))
    #xx_3_c_gpu = cl_array.to_device(queue, xx_3_c.astype(np.float32))
    ##test_meml_gpu(xx_1_stag_gpu)
    ##test_meml_kernel(queue, (N1,N2,N3), (WGPSIZE_1, WGPSIZE_2, WGPSIZE_3), xx_1_stag_gpu.data, N1, N2, N3)
    #mu_1_gpu = cl_array.to_device(queue, mu_1.astype(np.float32))
    #mu_2_gpu = cl_array.to_device(queue, mu_2.astype(np.float32))
    #mu_3_gpu = cl_array.to_device(queue, mu_3.astype(np.float32))
    #fe_1_gpu = cl_array.to_device(queue, fe[:,0].astype(np.int32)) 
    #fe_2_gpu = cl_array.to_device(queue, fe[:,1].astype(np.int32)) 
    #CE_gpu = cl_array.to_device(queue, CE.astype(np.int32)) 
    CX_gpu = cl_array.to_device(queue, CX.astype(np.int32)) 
    count_el_gpu = cl_array.to_device(queue, ne.reshape(-1).astype(np.int32)) 
    CX_old_gpu = cl_array.to_device(queue, CX.astype(np.int32)) 
    break_spec_gpu = cl_array.to_device(queue, CX.astype(np.float32)) 
    CX_el_gpu = cl_array.to_device(queue, CX_el.astype(np.int32)) 
    make_spec_gpu = cl_array.to_device(queue, CX_el.astype(np.float32)) 
    myfun_gpu = cl_array.to_device(queue, myfuntable.astype(np.float32))

    monitor = np.zeros((N_spec,1))
    monitor_gpu = cl_array.to_device(queue, monitor.astype(np.int32))
    #print f_1_flat_gpu.get()
    #print preind_1.get()
    #print preamt_1.get()
    #scan_knl(f_1_flat_gpu,preind_1,preamt_1) 
    #print f_1_flat_gpu.get()
    #sys.exit()

    #retet()
    CHECK_TET_FLAG = 0

    #ad hoc - put in d'Alembert form eventually
    rho_1_extra_gpu = cl_array.empty_like(u_1_gpu) 
    rho_2_extra_gpu = cl_array.empty_like(u_1_gpu) 
    rho_3_extra_gpu = cl_array.empty_like(u_1_gpu) 

    en = np.zeros((1,1))
    en_gpu = cl_array.to_device(queue, en.astype(np.float32))
    en_sum = np.zeros((N_tet,1))
    en_sum_gpu = cl_array.to_device(queue, en_sum.astype(np.float32))

    zero_gpu(en_gpu)
    calc_energy_volume_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, N_tri_one, en_gpu.data) 
    vol_th = np.abs(en_gpu.get()[0])

    #find target volume
    if INNIE:
        zero_gpu(en_gpu)
        calc_energy_volume_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, N_tri, en_gpu.data) 
        vol_t = v_red*np.abs(en_gpu.get()[0])
        zero_gpu(en_gpu)
        calc_total_area_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, k_area, N_tri, en_gpu.data) 
        ar = en_gpu.get()[0]

    #solve
    queue.finish()
    start_time = time.time()
    Z_ct = 0
    ZZ_old = 100
    START_CT = 1000
    aermax = 0
    aermean = 0
    vermax = 0
    for t_step in range(1, clock_max+1):
        solve(t_step)
        zero_gpu(A_ch_gpu)
        calc_change_area_kernel(queue, (N_tri, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, k_area, N_tri, A_ch_gpu.data) 
        if (np.max(np.abs(A_ch_gpu.get())) > aermax):
            aermax = np.max(np.abs(A_ch_gpu.get())) 
        if (np.mean(np.abs(A_ch_gpu.get())) > aermean):
            aermean = np.mean(np.abs(A_ch_gpu.get())) 
        if t_step == 5000:
            s_00 = 0.5*10**(-2)
            #kbrk = 100
        #if t_step == 200:
        #    dt = 0.005*dx3
        #if t_step == 400: #max with k_bulk = 1
        #    dt = 0.025*dx3
        #if t_step == 1000: #max with k_bulk = 0.01
        #    dt = 0.4*dx3
        #if t_step == 1000: #max with k_bulk = 0.01
        #    dt = 0.015*dx3
            #dt = 0.01*dx3
            #dt = 0.005*dx3
        #if t_step == 1000:
        #    dt = 0.05*dx1
        #if t_step == 2000:
        #    dt = 0.04*dx3
        #if t_step == 800:
        #    dt = 0.6*dx1
        if 0:
        #if t_step > START_CT:
            vis_X_1 = X_1_gpu.get()[0:N_r]
            vis_X_2 = X_2_gpu.get()[0:N_r]
            vis_X_3 = X_3_gpu.get()[0:N_r]
            X_1_ct = (vis_X_1-np.mean(vis_X_1))
            X_2_ct = (vis_X_2-np.mean(vis_X_2))
            X_3_ct = (vis_X_3-np.mean(vis_X_3))
            if (X_3_ct[0] > 0.0 and ZZ_old <= 0.0):
                Z_ct = Z_ct + 1
                print 'Z_ct is', Z_ct
                if (Z_ct == 2):
                    print 'freq is', 1/((t_step-START_Z)*dt)
                    sys.exit()
                START_Z = t_step 
            ZZ_old = X_3_ct[0]
        if t_step % DISP_INT == 0:
            print t_step
            print 'u_1 max is', u_1_gpu.get().max()
            if (u_1_gpu.get().max() > 10.0):
                sys.exit()
            print 'u_2 max is', u_2_gpu.get().max()
            print 'u_3 max is', u_3_gpu.get().max()
            print 'rho_1 max is', rho_1_gpu.get().max()
            print 'rho_1 min is', rho_1_gpu.get().min()
            #print 'mom1 is', (u_1_gpu.get()*(rho_1_gpu.get())).sum()*dx1*dx2*dx3
            #print 'mom2 is', (u_2_gpu.get()*(rho_2_gpu.get())).sum()*dx1*dx2*dx3
            #print 'mom3 is', (u_3_gpu.get()*(rho_3_gpu.get())).sum()*dx1*dx2*dx3
            print 'mom1 is', (u_1_gpu.get()).sum()*dx1*dx2*dx3
            print 'mom2 is', (u_2_gpu.get()).sum()*dx1*dx2*dx3
            print 'mom3 is', (u_3_gpu.get()).sum()*dx1*dx2*dx3
            print 'max rel error in area is', np.max(np.abs(A_ch_gpu.get()))
            print 'max until now at sampled pts', aermax 
            print 'avg rel error in area is', np.mean(np.abs(A_ch_gpu.get()))
            print 'max avg until now at sampled pts', aermean 
            zero_gpu(en_gpu)
            calc_energy_volume_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, N_tri_one, en_gpu.data) 
            print 'volume is', en_gpu.get()[0]
            if INNIE:
                #f.write('%g \n' % np.abs(en_gpu.get()[0]))
                s_0 = s_00 
                vol_th = vol_t/v_red-s_0*ar*dt*t_step
                if (vol_th < vol_t):
                    vol_th = vol_t
                print 'theoretical volume is', vol_th
            if (np.abs(en_gpu.get()-vol_th)/vol_th > vermax):
                vermax = np.abs(en_gpu.get()-vol_th)/vol_th 
            print 'max rel error in volume is', np.abs(en_gpu.get()-vol_th)/vol_th
            print 'max until now at sampled pts', vermax 
            zero_gpu(en_gpu)
            calc_total_area_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, k_area, N_tri_one, en_gpu.data) 
            print 'area is', en_gpu.get()[0]
            zero_gpu(en_gpu)
            calc_energy_area_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, A_0_gpu.data, k_area, N_tri_one, en_gpu.data) 
            en = en_gpu.get()[0]
            print 'area energy is', en 
            zero_gpu(en_gpu)
            calc_energy_curv_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, CT_gpu.data, CT_max, N_r, k_curv, en_gpu.data) 
            print 'mem curv energy is', en_gpu.get()[0] 
            zero_gpu(en_gpu)
            calc_energy_hook_kernel(queue, (1, 1), (1, 1), X_1_gpu.data, X_2_gpu.data, X_3_gpu.data, TV_1_gpu.data, TV_2_gpu.data, TV_3_gpu.data, X_ref_1_gpu.data, X_ref_2_gpu.data, X_ref_3_gpu.data, k_bulk, k_shear, N_tri, en_gpu.data) 
            print 'mem hook energy is', en_gpu.get()[0] 
            print 'area energy per mean curvature energy is', en/en_gpu.get()[0]
            CX = CX_gpu.get().reshape(-1)
            szE = np.count_nonzero(CX+1)/2
            print 'number of edges is', szE
            zero_gpu(monitor_gpu)
            monitor_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), CX_gpu.data, CX_max, monitor_gpu.data)
            print 'monitor 1 is', np.max(monitor_gpu.get())
            zero_gpu(monitor_gpu)
            count_make_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 0)
            #count_make_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 0)
            #count_make_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, CX_gpu.data, count_el_gpu.data, CX_max, 40000)
            print 'monitor 2 is', np.mean(count_el_gpu.get())
        if PR_INT:
            if (t_step-1) % PR_INT == 0:

                from os.path import join as pjoin
                ##vis_u_1 = u_1_gpu.get().reshape(N,N,1)
                #vis_u_1 = u_1_gpu.get()
                #file_name = "u_1-%04d.vts"%t_step
                #path_to_file = pjoin("vis_files", file_name) 
                #write_structured_grid(path_to_file, mesh3.reshape(3, N, N, N), 
                #point_data=[("u_1", vis_u_1)])

                ##vis_u_2 = u_2_gpu.get().reshape(N,N,1)
                #vis_u_2 = u_2_gpu.get()
                #file_name = "u_2-%04d.vts"%t_step
                #path_to_file = pjoin("vis_files", file_name) 
                #write_structured_grid(path_to_file, mesh3.reshape(3, N, N, N), 
                #point_data=[("u_2", vis_u_2)])

                ##vis_u_2 = u_2_gpu.get().reshape(N,N,1)
                #vis_u_3 = u_3_gpu.get()
                #file_name = "u_3-%04d.vts"%t_step
                #path_to_file = pjoin("vis_files", file_name) 
                #write_structured_grid(path_to_file, mesh3.reshape(3, N3, N2, N1), 
                #point_data=[("u_3", vis_u_3)])

                #vis_p = p_gpu.get()
                #write_structured_grid("p-%04d.vts"%t_step, mesh3, 
                #point_data=[("p", vis_p)])

                #vis_rho_2 = rho_2_gpu.get().reshape(N3,N2,N1)
                #file_name = "rho_2-%04d.vts"%t_step
                #path_to_file = pjoin("vis_files", file_name) 
                #write_structured_grid(path_to_file, mesh3.reshape(3, N3, N2, N1), 
                #point_data=[("rho_2", vis_rho_2)])

                #vis_X_1 = np.mod(X_1_gpu.get()+0.5,1.0)-0.5
                #vis_X_2 = np.mod(X_2_gpu.get()+0.5,1.0)-0.5
                #vis_X_3 = np.mod(X_3_gpu.get()+0.5,1.0)-0.5
                vis_X_1 = X_1_gpu.get()[N_r:N_r+N_vis]
                vis_X_2 = X_2_gpu.get()[N_r:N_r+N_vis]
                vis_X_3 = np.mod(X_3_gpu.get()[N_r:N_r+N_vis]+L3*0.5,L3)-0.5*L3
                #iii = np.hstack((np.arange(0,N_r), np.arange(N_r, b_q_orig)))
                #vis_X_3[0:b_q_orig] = X_3_gpu.get()[0:b_q_orig]-np.floor(X_3_gpu.get()[b_q_orig-1])
                #vis_X_3[iii] = X_3_gpu.get()[iii]-np.floor(X_3_gpu.get()[N_r-1])
                #vis_X_3[iii] = X_3_gpu.get()[iii]-np.mean(X_3_gpu.get()[iii])

                vis_X = np.hstack((vis_X_1,vis_X_2,vis_X_3)).copy()
                data = [
                #("F_1", F_1_gpu.get().reshape(b_q).copy()),
                #("F_2", F_2_gpu.get().reshape(b_q).copy()),
                #("F_3", F_3_gpu.get().reshape(b_q).copy())
                ]


                file_name = "trit-%04d.vtu"%t_step
                compressor = None
                cell_data = []
                point_data = []
                
                #F_vis = np.zeros(N_r)
                #F_vis[0:1075] = 1.0
                #F_vis[N_r_one:N_r_one+1075] = 1.0
                #F_vis[2*N_r_one:2*N_r_one+1075] = 1.0
                #point_data = [
                #("F", F_vis)
                #]

                for i in range(0,num_rbc):
                    vis_X_1 = X_1_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    vis_X_2 = X_2_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    vis_X_3 = X_3_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    shft = np.floor((vis_X_3[0]+L3*0.5)/L3)
                    vis_X_3 = vis_X_3 - L3*shft
                    if (i == 0):
                        vis_X = np.hstack((vis_X_1,vis_X_2,vis_X_3))
                    else: 
                        vis_X = np.vstack((vis_X,np.hstack((vis_X_1,vis_X_2,vis_X_3))))
                
                for i in range(0,num_rbc):
                    vis_X_1 = X_1_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    vis_X_2 = X_2_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    vis_X_3 = X_3_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    shft = 1 + np.floor((vis_X_3[0]+L3*0.5)/L3)
                    vis_X_3 = vis_X_3 - L3*shft
                    vis_X = np.vstack((vis_X,np.hstack((vis_X_1,vis_X_2,vis_X_3))))
                
                for i in range(0,num_rbc):
                    vis_X_1 = X_1_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    vis_X_2 = X_2_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    vis_X_3 = X_3_gpu.get()[i*N_r_one:(i+1)*N_r_one]
                    shft = -1 + np.floor((vis_X_3[0]+L3*0.5)/L3)
                    vis_X_3 = vis_X_3 - L3*shft
                    vis_X = np.vstack((vis_X,np.hstack((vis_X_1,vis_X_2,vis_X_3))))
                
                #vis_X_1 = X_1_gpu.get()[0:N_r]
                #vis_X_2 = X_2_gpu.get()[0:N_r]
                #vis_X_3 = X_3_gpu.get()[0:N_r]
                #vis_X_1 = (vis_X_1-np.mean(vis_X_1))
                #vis_X_2 = (vis_X_2-np.mean(vis_X_2))
                #vis_X_3 = (vis_X_3-np.mean(vis_X_3))

                #vis_X = np.hstack((vis_X_1,vis_X_2,vis_X_3)).copy()

                grid = UnstructuredGrid(
                    (3*N_r,
                    DataArray("points", vis_X,
                    vector_format=VF_LIST_OF_VECTORS)),
                    cells=np.vstack((TV_gpu.get(),N_r+TV_gpu.get(),2*N_r+TV_gpu.get())).reshape(-1),
                    cell_types=np.asarray([VTK_TRIANGLE] * 3*(TV_gpu.get().shape[0]), dtype=np.uint32))

                for name, field in point_data:
                    grid.add_pointdata(DataArray(name, field,
                    vector_format=VF_LIST_OF_COMPONENTS))

                for name, field in cell_data:
                    grid.add_celldata(DataArray(name, field,
                    vector_format=VF_LIST_OF_COMPONENTS))

                from os.path import exists
                path_to_file = pjoin("vis_files", file_name)
                if exists(path_to_file):
                   raise RuntimeError("output file '%s' already exists"
                   % path_to_file)

                outf = open(path_to_file, "w")
                AppendedDataXMLGenerator(compressor)(grid).write(outf)
                outf.close()

                file_name = "X-%04d.vtu"%t_step
                data = []
                compressor = None
                vis_Xtmp = vis_X[0,:].copy()
                vis_X = np.vstack((vis_Xtmp, vis_X[N_r_one,:])).copy()
                NN_vis = 2

                grid = UnstructuredGrid(
                     (NN_vis, DataArray("points", vis_X, vector_format=VF_LIST_OF_VECTORS)),
                     cells=np.arange(NN_vis, dtype=np.uint32),
                     cell_types=np.asarray([VTK_VERTEX] * NN_vis, dtype=np.uint8))

                for name, field in data:
                   grid.add_pointdata(DataArray(name, field,
                   vector_format=VF_LIST_OF_COMPONENTS))

                from os.path import exists
                path_to_file = pjoin("vis_files", file_name)
                if exists(path_to_file):
                   raise RuntimeError("output file '%s' already exists"
                   % path_to_file)

                outf = open(path_to_file, "w")
                AppendedDataXMLGenerator(compressor)(grid).write(outf)
                outf.close()

                file_name = "edges-%04d.vtu"%t_step
                compressor = None
                cell_data = []
                point_data = []
                
                vis_X_1 = X_1_gpu.get()[N_r:N_r+N_spec]
                vis_X_2 = X_2_gpu.get()[N_r:N_r+N_spec]
                vis_X_3 = X_3_gpu.get()[N_r:N_r+N_spec]
                shft = np.floor((vis_X_3[0]+L3*0.5)/L3)
                vis_X_3 = vis_X_3 - L3*shft
                vis_X = np.hstack((vis_X_1,vis_X_2,vis_X_3)).copy()

                #recompute fe
                start_time = time.time()
                CX = CX_gpu.get().reshape(-1)
                if (np.mod(np.count_nonzero(CX+1),2) == 1):
                    print 'CX bug'
                    sys.exit()
                szE = np.count_nonzero(CX+1)/2
                ne = np.zeros((N_spec,1))
                #print 'number of edges is', szE
                myfe = np.zeros((szE,2))
                eind = 0
                for ii in range(0,N_spec):
                    for jj in range(0,CX_max):
                        if (ii < CX[jj+CX_max*ii]):
                            myfe[eind,0] = ii 
                            myfe[eind,1] = CX[jj+CX_max*ii] 
                            ne[ii] += 1
                            ne[CX[jj+CX_max*ii]] += 1
                            eind += 1
                print 'time spent making myfe', time.time()-start_time, 'seconds'

                #get length and density distributions
                start_time = time.time()
                elengths = np.zeros((szE,1))
                for ii in range(0,szE):
                    elengths[ii] = np.sqrt((vis_X_1[myfe[ii,0]]-vis_X_1[myfe[ii,1]])*(vis_X_1[myfe[ii,0]]-vis_X_1[myfe[ii,1]])
                                  +(vis_X_2[myfe[ii,0]]-vis_X_2[myfe[ii,1]])*(vis_X_2[myfe[ii,0]]-vis_X_2[myfe[ii,1]])
                                  +(vis_X_3[myfe[ii,0]]-vis_X_3[myfe[ii,1]])*(vis_X_3[myfe[ii,0]]-vis_X_3[myfe[ii,1]]))

                N_bins = 50
                hist, bins = np.histogram(elengths, range = (0,L_cont), bins=N_bins, density=True) 
                file_name = "elengths-%04d.txt"%t_step
                path_to_file = pjoin("vis_files", file_name)
                np.savetxt(path_to_file, hist)
                #np.savetxt(path_to_file, elengths)
                    
                N_bins = 20
                print np.mean(ne)
                print np.max(ne)
                hist, bins = np.histogram(ne, range = (0,N_bins), bins=N_bins, density=True) 
                file_name = "neighs-%04d.txt"%t_step
                path_to_file = pjoin("vis_files", file_name)
                np.savetxt(path_to_file, hist)

                #update_spec_routine(queue, firstn_spec_gpu, nextn_spec_gpu, X_1_tilde_gpu, X_2_tilde_gpu, X_3_tilde_gpu, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec)
                count_make_distr_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, count_el_gpu.data, 0)
                #count_make_distr_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, count_el_gpu.data, 0)
                #count_make_distr_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, count_el_gpu.data, 40000)
                print 'monitor 3 is', np.mean(count_el_gpu.get())
                CX_el_sz = np.sum(count_el_gpu.get())
                simple_scan_knl(count_el_gpu, queue=queue)
                fill_make_distr_kernel(queue, (N_spec, 1), (b_WGPSIZE_4, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, count_el_gpu.data, CX_el_gpu.data, 0)
                #fill_make_distr_kernel(queue, (40000, 1), (400, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, count_el_gpu.data, CX_el_gpu.data, 0)
                #fill_make_distr_kernel(queue, (N_spec-40000, 1), (1, 1), X_1_tilde_gpu.data, X_2_tilde_gpu.data, X_3_tilde_gpu.data, firstn_spec_gpu.data, nextn_spec_gpu.data, N_pre_spec, N1_spec, N2_spec, N3_spec, dx1_spec, dx2_spec, dx3_spec, L_cont, count_el_gpu.data, CX_el_gpu.data, 40000)

                count_el = count_el_gpu.get()
                CX_el = CX_el_gpu.get()
                dists = np.zeros((CX_el_sz,1)) 
                for ii in range(0,N_spec):
                    if (ii == 0):
                        ne_el = count_el[0]
                    else:
                        ne_el = count_el[ii]-count_el[ii-1]
                    if (ii == 0):
                        st_ind = 0
                    else:
                        st_ind = count_el[ii-1]
                    for j in range(0,ne_el):
                        jj = CX_el[j+st_ind]
                        dists[j+st_ind] = np.sqrt((vis_X_1[ii]-vis_X_1[jj])*(vis_X_1[ii]-vis_X_1[jj])
                                  +(vis_X_2[ii]-vis_X_2[jj])*(vis_X_2[ii]-vis_X_2[jj])
                                  +(vis_X_3[ii]-vis_X_3[jj])*(vis_X_3[ii]-vis_X_3[jj]))

                N_bins = 50
                hist, bins = np.histogram(dists, range = (0,L_cont), bins=N_bins, density=True) 
                file_name = "dists-%04d.txt"%t_step
                path_to_file = pjoin("vis_files", file_name)
                np.savetxt(path_to_file, hist)
                #np.savetxt(path_to_file, dists)
                print 'time spent getting distribs', time.time()-start_time, 'seconds'
                file_name = "edges-%04d.vtu"%t_step

                ##test
                #ind=np.lexsort((myfe[:,1],myfe[:,0]))    
                #ind2=np.lexsort((fe[:,1],fe[:,0]))    
                #print fe[ind2[0]]
                #print fe[ind2[1]]
                #print myfe[ind[0]]
                #print myfe[ind[1]]
                #print np.max(fe[ind2]-myfe[ind])
                #print np.max(fe)
                #sys.exit()

                grid = UnstructuredGrid(
                    (N_spec,
                    DataArray("points", vis_X,
                    vector_format=VF_LIST_OF_VECTORS)),
                    cells=myfe.reshape(-1),
                    cell_types=np.asarray([VTK_LINE] * (myfe.shape[0]), dtype=np.uint32))

                for name, field in point_data:
                    grid.add_pointdata(DataArray(name, field,
                    vector_format=VF_LIST_OF_COMPONENTS))

                for name, field in cell_data:
                    grid.add_celldata(DataArray(name, field,
                    vector_format=VF_LIST_OF_COMPONENTS))

                from os.path import exists
                path_to_file = pjoin("vis_files", file_name)
                if exists(path_to_file):
                   raise RuntimeError("output file '%s' already exists"
                   % path_to_file)

                outf = open(path_to_file, "w")
                AppendedDataXMLGenerator(compressor)(grid).write(outf)
                outf.close()

                vis_X_1 = X_1_gpu.get()[N_r:N_r+N_spec]
                vis_X_2 = X_2_gpu.get()[N_r:N_r+N_spec]
                vis_X_3 = X_3_gpu.get()[N_r:N_r+N_spec]
                shft = np.floor((vis_X_3[0]+L3*0.5)/L3)
                vis_X_3 = vis_X_3 - L3*shft
                vis_X = np.hstack((vis_X_1,vis_X_2,vis_X_3)).copy()

                file_name = "Xspec-%04d.vtu"%t_step
                data = []
                compressor = None

                grid = UnstructuredGrid(
                     (N_spec, DataArray("points", vis_X, vector_format=VF_LIST_OF_VECTORS)),
                     cells=np.arange(N_spec, dtype=np.uint32),
                     cell_types=np.asarray([VTK_VERTEX] * N_spec, dtype=np.uint8))

                for name, field in data:
                   grid.add_pointdata(DataArray(name, field,
                   vector_format=VF_LIST_OF_COMPONENTS))

                from os.path import exists
                path_to_file = pjoin("vis_files", file_name)
                if exists(path_to_file):
                   raise RuntimeError("output file '%s' already exists"
                   % path_to_file)

                outf = open(path_to_file, "w")
                AppendedDataXMLGenerator(compressor)(grid).write(outf)
                outf.close()

                #file_name = "tet-%04d.vtu"%t_step
                #compressor = None
                #cell_data = []
                #point_data = []

                #grid = UnstructuredGrid(
                #    (b_q,
                #    DataArray("points", vis_X,
                #    vector_format=VF_LIST_OF_VECTORS)),
                #    cells=TW.reshape(-1),
                #    cell_types=np.asarray([VTK_TETRA] * TW.shape[0], dtype=np.uint32))

                #for name, field in point_data:
                #    grid.add_pointdata(DataArray(name, field,
                #    vector_format=VF_LIST_OF_COMPONENTS))

                #for name, field in cell_data:
                #    grid.add_celldata(DataArray(name, field,
                #    vector_format=VF_LIST_OF_COMPONENTS))

                #from os.path import exists
                #path_to_file = pjoin("vis_files", file_name)
                #if exists(path_to_file):
                #   raise RuntimeError("output file '%s' already exists"
                #   % path_to_file)

                #outf = open(path_to_file, "w")
                #AppendedDataXMLGenerator(compressor)(grid).write(outf)
                #outf.close()

    queue.finish()
    print 'time spent is', time.time()-start_time, 'seconds'

    u_1_soln = u_1_gpu.get()
    u_2_soln = u_2_gpu.get()
    u_3_soln = u_3_gpu.get()
    #print u_1_soln
    #print u_2_soln
    #calculate error
    if ii != start_size: 
        errinf1, errinf2, errinf3, err11, err12, err13, err21, err22, err23 = err(u_1_soln, u_2_soln, u_3_soln, u_1_o, u_2_o, u_3_o)

    #errinf1, errinf2, errinf3, err11, err12, err13, err21, err22, err23 = err_ex(clock_max, u_1_soln, u_2_soln, u_3_soln)
        print 'u Errinf1 is', errinf1, '\n u Errinf2 is', errinf2, '\n u Errinf3 is', errinf3
        print 'u Err11 is', err11, '\n u Err12 is', err12, '\n u Err13 is', err13
        print 'u Err21 is', err21, '\n u Err22 is', err22, '\n u Err23 is', err23

    u_1_o = u_1_soln
    u_2_o = u_2_soln

    #print 'Z_ct is', Z_ct
    #print 'freq is', Z_ct/((clock_max-START_CT)*dt)

#vis_X_1 = X_1_gpu.get()
#vis_X_2 = X_2_gpu.get()
#vis_X_3 = X_3_gpu.get()
#vis_X_1 = (vis_X_1-np.mean(X_1_gpu.get()[0:N_r]))
#vis_X_2 = (vis_X_2-np.mean(X_2_gpu.get()[0:N_r]))
#vis_X_3 = (vis_X_3-np.mean(X_3_gpu.get()[0:N_r]))
#vis_X = np.hstack((vis_X_1,vis_X_2,vis_X_3))
#vis_X = vis_X[N_r+N_teth-fX.shape[0]:N_r+N_teth,:]
#np.savetxt('/home/tfai/workdocs/gpu_code/test14.txt', vis_X)
#np.savetxt('/home/tfai/workdocs/gpu_code/test24.txt', fe)
#f.close()
